diff --git a/dockerRunner.sh b/dockerRunner.sh
deleted file mode 100755
index fc2adb2ac..000000000
--- a/dockerRunner.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-
-# Handle closing application on signal interrupt (ctrl + c)
-trap 'kill $CONTINUOUS_BUILD_PID $SERVER_PID; gradle --stop; exit' INT
-
-# Reset log file content for new application boot
-echo "*** Logs for 'gradle installBootDist --continuous' ***" > builder.log
-echo "*** Logs for 'gradle bootRun' ***" > runner.log
-
-# Print that the application is starting in watch mode
-echo "starting application in watch mode..."
-
-# Start the continious build listener process
-echo "starting continuous build listener..."
-gradle build --continuous 2>&1 | tee builder.log & CONTINUOUS_BUILD_PID=$!
-
-# Start server process once initial build finishes  
-( while ! grep -m1 'BUILD SUCCESSFUL' < builder.log; do
-    sleep 15
-done
-echo "starting crd server..."
-gradle bootRun 2>&1 | tee runner.log ) & SERVER_PID=$!
-
-# Handle application background process exiting
-wait $CONTINUOUS_BUILD_PID $SERVER_PID
-EXIT_CODE=$?
-echo "application exited with exit code $EXIT_CODE..."
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a4b442974..ffed3a254 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/operations/build.gradle b/operations/build.gradle
index 7f536fdf0..600a57e9e 100644
--- a/operations/build.gradle
+++ b/operations/build.gradle
@@ -1,7 +1,7 @@
-apply plugin: 'maven'
+apply plugin: 'maven-publish'
 
 dependencies {
-    compile project(':resources')
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-base:5.3.0'
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:5.3.0'
+    implementation project(':resources')
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-base:5.3.0'
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:5.3.0'
 }
diff --git a/resources/build.gradle b/resources/build.gradle
index c43254ba9..692387e0c 100644
--- a/resources/build.gradle
+++ b/resources/build.gradle
@@ -1,22 +1,22 @@
-apply plugin: 'maven'
+apply plugin: 'maven-publish'
 
 dependencies {
-    compile group: 'com.helger', name: 'ph-schematron', version: '4.1.0'
-    compile 'com.googlecode.json-simple:json-simple:1.1.1'
+    implementation group: 'com.helger', name: 'ph-schematron', version: '4.1.0'
+    implementation 'com.googlecode.json-simple:json-simple:1.1.1'
 
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-base:5.3.0'
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:5.3.0'
-    compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-validation-resources-r4', version: '5.3.0'
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-validation:5.3.0'
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-base:5.3.0'
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:5.3.0'
+    implementation group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-validation-resources-r4', version: '5.3.0'
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-validation:5.3.0'
 
-    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1'
-    compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.12.1'
-    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1'
+    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1'
+    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.12.1'
+    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1'
 
-    compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
-    compile group: 'org.springframework', name: 'spring-context', version: '5.0.8.RELEASE'
+    implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
+    implementation group: 'org.springframework', name: 'spring-context', version: '5.0.8.RELEASE'
 
-    compile('ca.uhn.hapi.fhir:hapi-fhir-jpaserver-base:3.6.0'){
+    implementation('ca.uhn.hapi.fhir:hapi-fhir-jpaserver-base:3.6.0'){
             exclude group: 'org.thymeleaf'
     }
 }
diff --git a/resources/src/main/java/org/cdshooks/Action.java b/resources/src/main/java/org/cdshooks/Action.java
index 84cf4b44e..edac2a4ef 100755
--- a/resources/src/main/java/org/cdshooks/Action.java
+++ b/resources/src/main/java/org/cdshooks/Action.java
@@ -15,6 +15,7 @@ public Action(FhirComponentsT fhirComponents) {
   private TypeEnum type = null;
   private String description = null;
   private IBaseResource resource = null;
+  private String resourceId = null;
 
   private FhirComponentsT fhirComponents;
 
@@ -26,9 +27,7 @@ public void setType(TypeEnum type) {
     this.type = type;
   }
 
-  public String getDescription() {
-    return description;
-  }
+  public String getDescription() { return description; }
 
   public void setDescription(String description) {
     this.description = description;
@@ -36,7 +35,14 @@ public void setDescription(String description) {
 
   public IBaseResource getResource() { return resource; }
 
-  public void setResource(IBaseResource resource) { this.resource = resource; }
+  public void setResource(IBaseResource resource) {
+    this.resource = resource;
+    setResourceId(resource.fhirType() + "/" + resource.getIdElement().getIdPart());
+  }
+
+  public String getResourceId() { return resourceId; }
+
+  public void setResourceId(String resourceId) { this.resourceId = resourceId; }
 
   public FhirComponentsT getFhirComponents() {
     return this.fhirComponents;
diff --git a/resources/src/main/java/org/cdshooks/ActionSerializer.java b/resources/src/main/java/org/cdshooks/ActionSerializer.java
index c22dc6b03..4b2a4448d 100644
--- a/resources/src/main/java/org/cdshooks/ActionSerializer.java
+++ b/resources/src/main/java/org/cdshooks/ActionSerializer.java
@@ -38,6 +38,8 @@ public void serialize(
         new ObjectMapper().readValue(jsonStrNew, HashMap.class);
     jgen.writeObjectField("resource", map);
 
+    jgen.writeStringField("resourceId", value.getResourceId());
+
     jgen.writeEndObject();
   }
 }
diff --git a/resources/src/main/java/org/cdshooks/Card.java b/resources/src/main/java/org/cdshooks/Card.java
index 73d8d2358..a4b125703 100755
--- a/resources/src/main/java/org/cdshooks/Card.java
+++ b/resources/src/main/java/org/cdshooks/Card.java
@@ -5,16 +5,24 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 
 public class Card {
+  private String uuid = null;
   private String summary = null;
-
   private String detail = null;
   private IndicatorEnum indicator = null;
   private Source source = null;
   private List<Suggestion> suggestions = null;
+  private SelectionBehaviorEnum selectionBehavior = null;
   private List<Link> links = null;
 
+  public Card() { this.uuid = UUID.randomUUID().toString(); }
+
+  public String getUuid() { return uuid; }
+
+  private void setUuid(String uuid) { this.uuid = uuid; }
+
   public String getSummary() {
     return summary;
   }
@@ -68,6 +76,10 @@ public void setSuggestions(List<Suggestion> suggestions) {
     this.suggestions = suggestions;
   }
 
+  public SelectionBehaviorEnum getSelectionBehavior() { return selectionBehavior; }
+
+  public void setSelectionBehavior(SelectionBehaviorEnum selectionBehavior) { this.selectionBehavior = selectionBehavior; }
+
   /**
    * Add a link.
    * @param linksItem The link.
@@ -129,4 +141,38 @@ public String toString() {
       return String.valueOf(value);
     }
   }
+
+  public enum SelectionBehaviorEnum {
+    ANY("any"),
+    AT_MOST_ONE("at-most-one");
+
+    private String value;
+
+    SelectionBehaviorEnum(String value) { this.value = value; }
+
+    /**
+     * Create the enum value from a string. Needed because the values have illegal java chars.
+     * @param value One of the enum values.
+     * @return selectionBehaviorEnum
+     */
+    @JsonCreator
+    public static SelectionBehaviorEnum fromValue(String value) throws IOException {
+      for (SelectionBehaviorEnum selectionBehaviorEnum : SelectionBehaviorEnum.values()) {
+        if (selectionBehaviorEnum.toString().equals(value)) {
+          return selectionBehaviorEnum;
+        }
+      }
+      return null;
+    }
+
+    @JsonValue
+    public String getValue() {
+      return value;
+    }
+
+    @Override
+    public String toString() {
+      return String.valueOf(value);
+    }
+  }
 }
diff --git a/resources/src/main/java/org/cdshooks/CoverageRequirements.java b/resources/src/main/java/org/cdshooks/CoverageRequirements.java
index 28be93d9b..cea3e3908 100644
--- a/resources/src/main/java/org/cdshooks/CoverageRequirements.java
+++ b/resources/src/main/java/org/cdshooks/CoverageRequirements.java
@@ -1,5 +1,7 @@
 package org.cdshooks;
 
+import java.util.UUID;
+
 public class CoverageRequirements {
   private boolean applies;
   private String summary;
@@ -12,10 +14,14 @@ public class CoverageRequirements {
   private String questionnairePARequestUri;
   private String questionnairePlanOfCareUri;
   private String questionnaireDispenseUri;
+  private String questionnaireAdditionalUri;
   private String requestId;
   private boolean priorAuthRequired;
   private boolean documentationRequired;
 
+  private boolean priorAuthApproved;
+  private String priorAuthId;
+
   public boolean getApplies() { return applies; }
 
   public CoverageRequirements setApplies(boolean applies) {
@@ -137,4 +143,32 @@ public CoverageRequirements setDocumentationRequired(boolean documentationRequir
     this.documentationRequired = documentationRequired;
     return this;
   }
+
+  public boolean isPriorAuthApproved() { return priorAuthApproved; }
+
+  public CoverageRequirements setPriorAuthApproved(boolean priorAuthApproved) {
+    this.priorAuthApproved = priorAuthApproved;
+    return this;
+  }
+
+  public String getPriorAuthId() { return priorAuthId; }
+
+  public CoverageRequirements setPriorAuthId(String priorAuthId) {
+    this.priorAuthId = priorAuthId;
+    return this;
+  }
+
+  public CoverageRequirements generatePriorAuthId() {
+    // Generate a random UUID as the ID. This is the same method that Prior Auth (PAS) uses.
+    this.priorAuthId = UUID.randomUUID().toString();
+    return this;
+  }
+
+  public String getQuestionnaireAdditionalUri() {
+    return questionnaireAdditionalUri;
+  }
+
+  public void setQuestionnaireAdditionalUri(String questionnaireAdditionalUri) {
+    this.questionnaireAdditionalUri = questionnaireAdditionalUri;
+  }
 }
diff --git a/resources/src/main/java/org/cdshooks/Suggestion.java b/resources/src/main/java/org/cdshooks/Suggestion.java
index e1c88aca1..0eb4e6d87 100755
--- a/resources/src/main/java/org/cdshooks/Suggestion.java
+++ b/resources/src/main/java/org/cdshooks/Suggestion.java
@@ -7,11 +7,13 @@
 public class Suggestion {
   private String label = null;
 
-  private UUID uuid = null;
+  private String uuid = null;
 
   private List<Action> actions = null;
 
-  private boolean isRecommended = false;
+  private boolean isRecommended = true;
+
+  public Suggestion() { this.uuid = UUID.randomUUID().toString(); }
 
   public String getLabel() {
     return label;
@@ -21,11 +23,9 @@ public void setLabel(String label) {
     this.label = label;
   }
 
-  public UUID getUuid() {
-    return uuid;
-  }
+  public String getUuid() { return uuid; }
 
-  public void setUuid(UUID uuid) {
+  public void setUuid(String uuid) {
     this.uuid = uuid;
   }
 
diff --git a/resources/src/main/java/org/hl7/davinci/r4/Utilities.java b/resources/src/main/java/org/hl7/davinci/r4/Utilities.java
index 6cfd033b4..e1821bc71 100644
--- a/resources/src/main/java/org/hl7/davinci/r4/Utilities.java
+++ b/resources/src/main/java/org/hl7/davinci/r4/Utilities.java
@@ -1,35 +1,16 @@
 package org.hl7.davinci.r4;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 import ca.uhn.fhir.context.FhirContext;
 import ca.uhn.fhir.parser.IParser;
-import org.hl7.davinci.FhirResourceInfo;
-import org.hl7.davinci.PatientInfo;
-import org.hl7.davinci.PractitionerRoleInfo;
-import org.hl7.davinci.RequestIncompleteException;
-import org.hl7.davinci.SharedUtilities;
-import org.hl7.davinci.SuppressParserErrorHandler;
+import org.hl7.davinci.*;
 import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.r4.model.Address;
+import org.hl7.fhir.r4.model.*;
 import org.hl7.fhir.r4.model.Address.AddressType;
 import org.hl7.fhir.r4.model.Address.AddressUse;
-import org.hl7.fhir.r4.model.Bundle;
 import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
-import org.hl7.fhir.r4.model.Coverage;
-import org.hl7.fhir.r4.model.DomainResource;
-import org.hl7.fhir.r4.model.Library;
-import org.hl7.fhir.r4.model.Location;
-import org.hl7.fhir.r4.model.Organization;
-import org.hl7.fhir.r4.model.Patient;
-import org.hl7.fhir.r4.model.PractitionerRole;
-import org.hl7.fhir.r4.model.Questionnaire;
-import org.hl7.fhir.r4.model.QuestionnaireResponse;
-import org.hl7.fhir.r4.model.Reference;
-import org.hl7.fhir.r4.model.Resource;
-import org.hl7.fhir.r4.model.ValueSet;
+import org.hl7.fhir.r4.model.ClaimResponse.AdjudicationComponent;
 
 public class Utilities {
   /**
@@ -248,4 +229,99 @@ public static FhirResourceInfo getFhirResourceInfo(String resourceString) {
     return getFhirResourceInfo(parseFhirData(resourceString));
   }
 
+  public static Reference convertIdToReference(String id, String fhirType) {
+    Reference reference = new Reference();
+    if (id.toUpperCase().startsWith(fhirType.toUpperCase() + "/")) {
+      reference.setReference(id);
+    } else {
+      reference.setReference(fhirType + "/" + id);
+    }
+    return reference;
+  }
+
+  public static ClaimResponse createClaimResponse(String priorAuthId, String patientId, String payerId, String providerId, String applicationFhirPath) {
+    Date now = new Date();
+
+    ClaimResponse claimResponse = new ClaimResponse();
+
+    claimResponse.setId(priorAuthId);
+
+    Meta meta = new Meta();
+    meta.addProfile("http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claimresponse");
+    claimResponse.setMeta(meta);
+
+    claimResponse.addIdentifier(new Identifier().setSystem(applicationFhirPath).setValue(claimResponse.getId()));
+
+    claimResponse.setStatus(ClaimResponse.ClaimResponseStatus.ACTIVE);
+
+    CodeableConcept codeableConcept = new CodeableConcept();
+    Coding coding = new Coding();
+    coding.setSystem("http://terminology.hl7.org/CodeSystem/claim-type");
+    coding.setCode("professional");
+    coding.setDisplay("Professional");
+    codeableConcept.addCoding(coding);
+    claimResponse.setType(codeableConcept);
+
+    claimResponse.setUse(ClaimResponse.Use.PREAUTHORIZATION);
+
+    claimResponse.setPatient(convertIdToReference(patientId, "Patient"));
+
+    claimResponse.setCreated(now);
+
+    claimResponse.setInsurer(convertIdToReference(payerId, "Organization"));
+
+    claimResponse.setOutcome(ClaimResponse.RemittanceOutcome.COMPLETE);
+
+    claimResponse.setDisposition("Granted");
+
+    claimResponse.setPreAuthRef(claimResponse.getId());
+
+    ClaimResponse.ItemComponent itemComponent = new ClaimResponse.ItemComponent();
+
+    Extension reviewActionExtension = new Extension();
+    reviewActionExtension.setUrl("http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewAction");
+    reviewActionExtension.addExtension(
+        new Extension()
+            .setUrl("http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewActionCode")
+            .setValue(new CodeableConcept().addCoding(
+                new Coding()
+                    .setSystem("https://valueset.x12.org/x217/005010/response/2000F/HCR/1/01/00/306")
+                    .setCode("A1"))));
+    reviewActionExtension.addExtension(
+        new Extension()
+            .setUrl("number")
+            .setValue(new StringType(UUID.randomUUID().toString())));
+    itemComponent.addExtension(reviewActionExtension);
+
+    itemComponent.addExtension(
+        new Extension()
+            .setUrl("http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-itemPreAuthIssueDate")
+            .setValue(new DateType().setValue(now)));
+
+    itemComponent.addExtension(
+        new Extension()
+            .setUrl("http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-authorizationNumber")
+            .setValue(new StringType(UUID.randomUUID().toString())));
+
+    Extension providerExtension = new Extension();
+    providerExtension.setUrl("http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-itemAuthorizedProvider");
+    providerExtension.addExtension(
+        new Extension()
+            .setUrl("provider")
+            .setValue(new Reference().setReference(convertIdToReference(providerId, "Practitioner").getReference())));
+    itemComponent.addExtension(providerExtension);
+
+    itemComponent.setItemSequence(1);
+
+    itemComponent.addAdjudication(
+        new AdjudicationComponent().setCategory(
+            new CodeableConcept().addCoding(
+                new Coding().setSystem("http://terminology.hl7.org/CodeSystem/adjudication")
+                    .setCode("submitted"))));
+
+    claimResponse.addItem(itemComponent);
+
+    return claimResponse;
+  }
+
 }
diff --git a/server/build.gradle b/server/build.gradle
index 33362bfad..cf9783546 100644
--- a/server/build.gradle
+++ b/server/build.gradle
@@ -5,7 +5,6 @@ buildscript {
     repositories {
         mavenCentral()
         maven { url 'https://repo.spring.io/snapshot' }
-        maven { url 'http://repo.jenkins-ci.org/releases/' }
 
     }
     dependencies {
@@ -13,7 +12,7 @@ buildscript {
     }
 }
 
-apply plugin: 'maven'
+apply plugin: 'maven-publish'
 //apply plugin: 'war'
 apply plugin: 'java'
 apply plugin: 'org.springframework.boot'
@@ -28,48 +27,50 @@ processResources {
 dependencies {
     developmentOnly("org.springframework.boot:spring-boot-devtools")
 
-    compile project(':resources')
-    compile project(':operations')
+    implementation project(':resources')
+    implementation project(':operations')
+    implementation 'com.googlecode.json-simple:json-simple:1.1.1'
+    implementation 'com.google.code.gson:gson:2.8.8'
 
-    compile('org.springframework.boot:spring-boot-starter-actuator')
-    compile('org.springframework.boot:spring-boot-starter-data-jpa')
-    compile('org.springframework.boot:spring-boot-starter-data-rest')
-    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
-    compile('org.springframework.boot:spring-boot-starter-security')
+    implementation('org.springframework.boot:spring-boot-starter-actuator')
+    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
+    implementation('org.springframework.boot:spring-boot-starter-data-rest')
+    implementation('org.springframework.boot:spring-boot-starter-thymeleaf')
+    implementation('org.springframework.boot:spring-boot-starter-security')
+    implementation('org.springframework.boot:spring-boot-starter-validation')
 
-    compile('com.h2database:h2')
+    implementation('com.h2database:h2')
 
-    compile("io.jsonwebtoken:jjwt:0.7.0")
+    implementation("io.jsonwebtoken:jjwt:0.7.0")
 
-//    compile 'javax.servlet:javax.servlet-api:3.1.0'
 
-    compile 'commons-beanutils:commons-beanutils:1.9.3'
+    implementation 'commons-beanutils:commons-beanutils:1.9.3'
 
-    testCompile('org.springframework.boot:spring-boot-starter-test')
-    testCompile "com.github.tomakehurst:wiremock-standalone:2.18.0"
-    testCompile('org.springframework.boot:spring-boot-starter-test')
+    testImplementation('org.springframework.boot:spring-boot-starter-test')
+    testImplementation "com.github.tomakehurst:wiremock-standalone:2.18.0"
+    testImplementation('org.springframework.boot:spring-boot-starter-test')
 
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-base:5.3.0'
-    compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:5.3.0'
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-base:5.3.0'
+    implementation 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:5.3.0'
 
-    compile 'com.jayway.jsonpath:json-path:2.4.0'
-    compile 'joda-time:joda-time:2.10.5'
+    implementation 'com.jayway.jsonpath:json-path:2.4.0'
+    implementation 'joda-time:joda-time:2.10.5'
 
     //cql stuff
-    compile (group: 'org.opencds.cqf.cql', name: 'engine', version: '1.5.1') {
+    implementation (group: 'org.opencds.cqf.cql', name: 'engine', version: '1.5.1') {
         exclude group: 'org.slf4j', module: 'slf4j-log4j12'
     }
-    compile (group: 'org.opencds.cqf.cql', name: 'engine.fhir', version: '1.5.1') {
+    implementation (group: 'org.opencds.cqf.cql', name: 'engine.fhir', version: '1.5.1') {
         exclude group: 'org.slf4j', module: 'slf4j-log4j12'
     }
 
     //Use locally compiled cql libs (engine and fhir)
-    compile fileTree(dir: 'libs', include: ['*.jar'])
-    compile group: 'info.cqframework', name: 'cql-to-elm', version: '1.5.1'
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation group: 'info.cqframework', name: 'cql-to-elm', version: '1.5.1'
 
-    compile 'org.zeroturnaround:zt-zip:1.13'
+    implementation 'org.zeroturnaround:zt-zip:1.13'
 
-    compile group: 'org.kohsuke', name:'github-api', version:'1.77'
+    implementation group: 'org.kohsuke', name:'github-api', version:'1.77'
 }
 
 task buildReact(type:Exec) {
@@ -142,7 +143,7 @@ void cloneCdsLibraryScript(branch) {
     println "GIT: clone CDS-Library branch " + branch
     exec {
         workingDir './'
-        commandLine 'git', 'clone', 'https://github.com/mcode/CDS-Library.git', 'CDS-Library'
+        commandLine 'git', 'clone', 'https://github.com/HL7-DaVinci/CDS-Library.git', 'CDS-Library'
     }
     checkoutCdsLibraryScript(branch)
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/Utils.java b/server/src/main/java/org/hl7/davinci/endpoint/Utils.java
index c85e2f452..4d407e93c 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/Utils.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/Utils.java
@@ -2,7 +2,6 @@
 
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import com.google.common.net.HttpHeaders;
 
@@ -39,27 +38,4 @@ public static URL getApplicationBaseUrl(HttpServletRequest request) {
     }
   }
 
-  public static String stripResourceType(String identifier) {
-    int indexOfDivider = identifier.indexOf('/');
-    if (indexOfDivider+1 == identifier.length()) {
-      // remove the trailing '/'
-      return identifier.substring(0, indexOfDivider);
-    } else {
-      return identifier.substring(indexOfDivider+1);
-    }
-  }
-
-  public static boolean idInSelectionsList(String identifier, List<String> selections) {
-    if (selections.isEmpty()) {
-      return true;
-    } else {
-      for ( String selection : selections) {
-        if (identifier.contains(stripResourceType(selection))) {
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsAbstract.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsAbstract.java
deleted file mode 100644
index 750e37322..000000000
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsAbstract.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package org.hl7.davinci.endpoint.cdshooks.services.crd;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.cdshooks.*;
-import org.hl7.davinci.FhirComponentsT;
-import org.hl7.davinci.PrefetchTemplateElement;
-import org.hl7.davinci.endpoint.config.YamlConfig;
-import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria;
-import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-@Component
-public abstract class CdsAbstract<requestTypeT extends CdsRequest<?, ?>>{
-    static final Logger logger = LoggerFactory.getLogger(CdsAbstract.class);
-
-    /**
-     * The {id} portion of the URL to this service which is available at
-     * {baseUrl}/cds-services/{id}. REQUIRED
-     */
-    public String id;
-
-    /**
-     * The hook this service should be invoked on. REQUIRED
-     */
-    public Hook hook;
-
-    /**
-     * The human-friendly name of this service. RECOMMENDED
-     */
-    public String title;
-
-    /**
-     * The description of this service. REQUIRED
-     */
-    public String description;
-
-    /**
-     * An object containing key/value pairs of FHIR queries that this service is
-     * requesting that the EHR prefetch and provide on each service call. The key is
-     * a string that describes the type of data being requested and the value is a
-     * string representing the FHIR query. OPTIONAL
-     */
-    public Prefetch prefetch;
-
-    private final List<PrefetchTemplateElement> prefetchElements;
-
-    protected FhirComponentsT fhirComponents;
-
-    private final DiscoveryExtension extension;
-
-    @Autowired
-    @JsonIgnore
-    public YamlConfig myConfig;
-
-    public CdsAbstract(String id, Hook hook, String title, String description,
-                      List<PrefetchTemplateElement> prefetchElements, FhirComponentsT fhirComponents,
-                      DiscoveryExtension extension) {
-
-        if (id == null) {
-            throw new NullPointerException("CDSService id cannot be null");
-        }
-        if (hook == null) {
-            throw new NullPointerException("CDSService hook cannot be null");
-        }
-        if (description == null) {
-            throw new NullPointerException("CDSService description cannot be null");
-        }
-        this.id = id;
-        this.hook = hook;
-        this.title = title;
-        this.description = description;
-        this.prefetchElements = prefetchElements;
-        prefetch = new Prefetch();
-        for (PrefetchTemplateElement prefetchElement : prefetchElements) {
-            this.prefetch.put(prefetchElement.getKey(), prefetchElement.getQuery());
-        }
-        this.fhirComponents = fhirComponents;
-        this.extension = extension;
-    }
-
-    public DiscoveryExtension getExtension() { return extension; }
-
-    public List<PrefetchTemplateElement> getPrefetchElements() {
-        return prefetchElements;
-    }
-
-    protected Link smartLinkBuilder(String patientId, String fhirBase, URL applicationBaseUrl, String questionnaireUri,
-                                  String reqResourceId, CoverageRequirementRuleCriteria criteria, boolean priorAuthRequired, String label) {
-        URI configLaunchUri = myConfig.getLaunchUrl();
-        questionnaireUri = applicationBaseUrl + "/fhir/r4/" + questionnaireUri;
-
-        String launchUrl;
-        if (myConfig.getLaunchUrl().isAbsolute()) {
-            launchUrl = myConfig.getLaunchUrl().toString();
-        } else {
-            try {
-                launchUrl = new URL(applicationBaseUrl.getProtocol(), applicationBaseUrl.getHost(),
-                        applicationBaseUrl.getPort(), applicationBaseUrl.getFile() + configLaunchUri.toString(), null).toString();
-            } catch (MalformedURLException e) {
-                String msg = "Error creating smart launch URL";
-                logger.error(msg);
-                throw new RuntimeException(msg);
-            }
-        }
-
-        if (fhirBase != null && fhirBase.endsWith("/")) {
-            fhirBase = fhirBase.substring(0, fhirBase.length() - 1);
-        }
-        if (patientId != null && patientId.startsWith("Patient/")) {
-            patientId = patientId.substring(8);
-        }
-
-        // PARAMS:
-        // template is the uri of the questionnaire
-        // request is the ID of the device request or medrec (not the full URI like the
-        // IG says, since it should be taken from fhirBase
-
-        String filepath = "../../getfile/" + criteria.getQueryString();
-
-        String appContext = "template=" + questionnaireUri + "&request=" + reqResourceId;
-        appContext = appContext + "&fhirpath=" + applicationBaseUrl + "/fhir/";
-
-        appContext = appContext + "&priorauth=" + (priorAuthRequired ? "true" : "false");
-        appContext = appContext + "&filepath=" + applicationBaseUrl + "/";
-        if (myConfig.getUrlEncodeAppContext()) {
-            logger.info("CdsService::smartLinkBuilder: URL encoding appcontext");
-            appContext = URLEncoder.encode(appContext, StandardCharsets.UTF_8).toString();
-        }
-
-        logger.info("smarLinkBuilder: appContext: " + appContext);
-
-        if (myConfig.isAppendParamsToSmartLaunchUrl()) {
-            launchUrl = launchUrl + "?iss=" + fhirBase + "&patientId=" + patientId + "&template=" + questionnaireUri
-                    + "&request=" + reqResourceId;
-        } else {
-            // TODO: The iss should be set by the EHR?
-            launchUrl = launchUrl;
-        }
-
-        Link link = new Link();
-        link.setType("smart");
-        link.setLabel(label);
-        link.setUrl(launchUrl);
-
-        link.setAppContext(appContext);
-
-        return link;
-    }
-
-    public abstract CdsResponse handleRequest(requestTypeT request, URL applicationBaseUrl);
-}
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java
index a2aec34ea..b5664cac2 100755
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java
@@ -1,19 +1,33 @@
 package org.hl7.davinci.endpoint.cdshooks.services.crd;
 
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Date;
+import javax.validation.Valid;
+
 import org.apache.commons.lang.StringUtils;
 import org.cdshooks.*;
 import org.hl7.davinci.FhirComponentsT;
 import org.hl7.davinci.PrefetchTemplateElement;
 import org.hl7.davinci.RequestIncompleteException;
+import org.hl7.davinci.endpoint.config.YamlConfig;
 import org.hl7.davinci.endpoint.components.CardBuilder;
 import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard;
 import org.hl7.davinci.endpoint.components.PrefetchHydrator;
+import org.hl7.davinci.endpoint.database.FhirResourceRepository;
 import org.hl7.davinci.endpoint.database.RequestLog;
 import org.hl7.davinci.endpoint.database.RequestService;
 import org.hl7.davinci.endpoint.files.FileStore;
+import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria;
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult;
-import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
 import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest;
+import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
 import org.opencds.cqf.cql.engine.execution.Context;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -21,26 +35,99 @@
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.RequestBody;
 
-import javax.validation.Valid;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
 @Component
-public abstract class CdsService<requestTypeT extends CdsRequest<?, ?>> extends CdsAbstract<requestTypeT> {
+public abstract class CdsService<requestTypeT extends CdsRequest<?, ?>> {
   static final Logger logger = LoggerFactory.getLogger(CdsService.class);
 
+  /**
+   * The {id} portion of the URL to this service which is available at
+   * {baseUrl}/cds-services/{id}. REQUIRED
+   */
+  public String id;
+
+  /**
+   * The hook this service should be invoked on. REQUIRED
+   */
+  public Hook hook;
+
+  /**
+   * The human-friendly name of this service. RECOMMENDED
+   */
+  public String title;
+
+  /**
+   * The description of this service. REQUIRED
+   */
+  public String description;
+
+  /**
+   * An object containing key/value pairs of FHIR queries that this service is
+   * requesting that the EHR prefetch and provide on each service call. The key is
+   * a string that describes the type of data being requested and the value is a
+   * string representing the FHIR query. OPTIONAL
+   */
+  public Prefetch prefetch;
+
+  @Autowired
+  private YamlConfig myConfig;
+
   @Autowired
   RequestService requestService;
 
   @Autowired
   FileStore fileStore;
 
+  @Autowired
+  private FhirResourceRepository fhirResourceRepository;
+
+  private final List<PrefetchTemplateElement> prefetchElements;
+
+  protected FhirComponentsT fhirComponents;
+
+  private final DiscoveryExtension extension;
+
+  /**
+   * Create a new cdsservice.
+   *
+   * @param id               Will be used in the url, should be unique.
+   * @param hook             Which hook can call this.
+   * @param title            Human title.
+   * @param description      Human description.
+   * @param prefetchElements List of prefetch elements, will be in prefetch
+   *                         template.
+   * @param fhirComponents   Fhir components to use
+   * @param extension        Custom CDS Hooks extensions.
+   */
   public CdsService(String id, Hook hook, String title, String description,
       List<PrefetchTemplateElement> prefetchElements, FhirComponentsT fhirComponents,
       DiscoveryExtension extension) {
-    super(id, hook, title, description, prefetchElements, fhirComponents, extension);
+
+    if (id == null) {
+      throw new NullPointerException("CDSService id cannot be null");
+    }
+    if (hook == null) {
+      throw new NullPointerException("CDSService hook cannot be null");
+    }
+    if (description == null) {
+      throw new NullPointerException("CDSService description cannot be null");
+    }
+    this.id = id;
+    this.hook = hook;
+    this.title = title;
+    this.description = description;
+    this.prefetchElements = prefetchElements;
+    prefetch = new Prefetch();
+    for (PrefetchTemplateElement prefetchElement : prefetchElements) {
+      this.prefetch.put(prefetchElement.getKey(), prefetchElement.getQuery());
+    }
+    this.fhirComponents = fhirComponents;
+    this.extension = extension;
+  }
+
+  public DiscoveryExtension getExtension() { return extension; }
+
+  public List<PrefetchTemplateElement> getPrefetchElements() {
+    return prefetchElements;
   }
 
   /**
@@ -105,22 +192,30 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
 
         if (results.getCoverageRequirements().getApplies()) {
 
-          if (coverageRequirements.isDocumentationRequired() || coverageRequirements.isPriorAuthRequired()) {
+          // if prior auth already approved
+          if (coverageRequirements.isPriorAuthApproved()) {
+            response.addCard(CardBuilder.priorAuthCard(results, results.getRequest(), fhirComponents, coverageRequirements.getPriorAuthId(),
+                request.getContext().getPatientId(), lookupResult.getCriteria().getPayorId(), request.getContext().getUserId(),
+                applicationBaseUrl.toString() + "/fhir/" + fhirComponents.getFhirVersion().toString(),
+                fhirResourceRepository));
+
+          } else if (coverageRequirements.isDocumentationRequired() || coverageRequirements.isPriorAuthRequired()) {
             if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireOrderUri())
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireFaceToFaceUri())
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireLabUri())
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireProgressNoteUri())
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnairePARequestUri())
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnairePlanOfCareUri())
-                || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireDispenseUri())) {
+                || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireDispenseUri())
+                || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireAdditionalUri())) {
               List<Link> smartAppLinks = createQuestionnaireLinks(request, applicationBaseUrl, lookupResult, results);
               response.addCard(CardBuilder.transform(results, smartAppLinks));
 
               // add a card for an alternative therapy if there is one
               if (results.getAlternativeTherapy().getApplies() && hookConfiguration.getAlternativeTherapy()) {
                 try {
-                  response.addCard(CardBuilder.alternativeTherapyCard(results.getAlternativeTherapy(), results.getRequest(),
-                      fhirComponents));
+                  response.addCard(CardBuilder.alternativeTherapyCard(results.getAlternativeTherapy(),
+                      results.getRequest(), fhirComponents));
                 } catch (RuntimeException e) {
                   logger.warn("Failed to process alternative therapy: " + e.getMessage());
                 }
@@ -133,7 +228,10 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
             // no prior auth or documentation required
             logger.info("Add the no doc or prior auth required card");
             Card card = CardBuilder.transform(results);
-            card = CardBuilder.createSuggestionsWithNote(card, results, fhirComponents);
+            card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents,
+                "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note",
+                true));
+            card.setSelectionBehavior(Card.SelectionBehaviorEnum.ANY);
             response.addCard(card);
           }
         }
@@ -157,7 +255,7 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
       CardBuilder.errorCardIfNonePresent(response);
     }
 
-    // Adding card to requestLog
+    // Ading card to requestLog
     requestLog.setCardListFromCards(response.getCards());
     requestService.edit(requestLog);
 
@@ -170,41 +268,47 @@ private List<Link> createQuestionnaireLinks(requestTypeT request, URL applicatio
     CoverageRequirements coverageRequirements = results.getCoverageRequirements();
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireOrderUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnaireOrderUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "Order Form"));
+          coverageRequirements.getQuestionnaireOrderUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Order Form"));
     }
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireFaceToFaceUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnaireFaceToFaceUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "Face to Face Encounter Form"));
+          coverageRequirements.getQuestionnaireFaceToFaceUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Face to Face Encounter Form"));
     }
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireLabUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnaireLabUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "Lab Form"));
+          coverageRequirements.getQuestionnaireLabUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Lab Form"));
     }
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireProgressNoteUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnaireProgressNoteUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "Progress Note"));
+          coverageRequirements.getQuestionnaireProgressNoteUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Progress Note"));
     }
 
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnairePARequestUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnairePARequestUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "PA Request"));
+          coverageRequirements.getQuestionnairePARequestUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "PA Request"));
     }
 
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnairePlanOfCareUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnairePlanOfCareUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "Plan of Care/Certification"));
+          coverageRequirements.getQuestionnairePlanOfCareUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Plan of Care/Certification"));
     }
 
     if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireDispenseUri())) {
       listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
-          coverageRequirements.getQuestionnaireDispenseUri(), coverageRequirements.getRequestId(), lookupResult.getCriteria(),
-          coverageRequirements.isPriorAuthRequired(), "Dispense Form"));
+          coverageRequirements.getQuestionnaireDispenseUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Dispense Form"));
+    }
+
+    if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireAdditionalUri())) {
+      listOfLinks.add(smartLinkBuilder(request.getContext().getPatientId(), request.getFhirServer(), applicationBaseUrl,
+          coverageRequirements.getQuestionnaireAdditionalUri(), coverageRequirements.getRequestId(),
+          lookupResult.getCriteria(), coverageRequirements.isPriorAuthRequired(), "Additional Form"));
     }
     return listOfLinks;
   }
@@ -222,7 +326,72 @@ protected Object evaluateStatement(String statement, Context context) {
     }
   }
 
+  private Link smartLinkBuilder(String patientId, String fhirBase, URL applicationBaseUrl, String questionnaireUri,
+      String reqResourceId, CoverageRequirementRuleCriteria criteria, boolean priorAuthRequired, String label) {
+    URI configLaunchUri = myConfig.getLaunchUrl();
+    questionnaireUri = applicationBaseUrl + "/fhir/r4/" + questionnaireUri;
+
+    String launchUrl;
+    if (myConfig.getLaunchUrl().isAbsolute()) {
+      launchUrl = myConfig.getLaunchUrl().toString();
+    } else {
+      try {
+        launchUrl = new URL(applicationBaseUrl.getProtocol(), applicationBaseUrl.getHost(),
+            applicationBaseUrl.getPort(), applicationBaseUrl.getFile() + configLaunchUri.toString(), null).toString();
+      } catch (MalformedURLException e) {
+        String msg = "Error creating smart launch URL";
+        logger.error(msg);
+        throw new RuntimeException(msg);
+      }
+    }
+
+    if (fhirBase != null && fhirBase.endsWith("/")) {
+      fhirBase = fhirBase.substring(0, fhirBase.length() - 1);
+    }
+    if (patientId != null && patientId.startsWith("Patient/")) {
+      patientId = patientId.substring(8);
+    }
 
+    // PARAMS:
+    // template is the uri of the questionnaire
+    // request is the ID of the device request or medrec (not the full URI like the
+    // IG says, since it should be taken from fhirBase
+
+    String filepath = "../../getfile/" + criteria.getQueryString();
+
+    String appContext = "template=" + questionnaireUri + "&request=" + reqResourceId;
+    appContext = appContext + "&fhirpath=" + applicationBaseUrl + "/fhir/";
+
+    appContext = appContext + "&priorauth=" + (priorAuthRequired ? "true" : "false");
+    appContext = appContext + "&filepath=" + applicationBaseUrl + "/";
+    if (myConfig.getUrlEncodeAppContext()) {
+      logger.info("CdsService::smartLinkBuilder: URL encoding appcontext");
+      try {
+        appContext = URLEncoder.encode(appContext, StandardCharsets.UTF_8.name()).toString();
+      } catch (UnsupportedEncodingException e) {
+        logger.error("CdsService::smartLinkBuilder: failed to encode URL: " + e.getMessage());
+      }
+    }
+
+    logger.info("smarLinkBuilder: appContext: " + appContext);
+
+    if (myConfig.isAppendParamsToSmartLaunchUrl()) {
+      launchUrl = launchUrl + "?iss=" + fhirBase + "&patientId=" + patientId + "&template=" + questionnaireUri
+          + "&request=" + reqResourceId;
+    } else {
+      // TODO: The iss should be set by the EHR?
+      launchUrl = launchUrl;
+    }
+
+    Link link = new Link();
+    link.setType("smart");
+    link.setLabel(label);
+    link.setUrl(launchUrl);
+
+    link.setAppContext(appContext);
+
+    return link;
+  }
 
   // Implement these in child class
   public abstract List<CoverageRequirementRuleResult> createCqlExecutionContexts(requestTypeT request,
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java
index ca7ea731c..2e08fbcbc 100755
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java
@@ -4,14 +4,14 @@
 import java.util.List;
 
 public class CdsServiceInformation {
-  private List<CdsAbstract> services = null;
+  private List<CdsService> services = null;
 
   /**
    * Add a service.
    * @param servicesItem The service.
    * @return
    */
-  public CdsServiceInformation addServicesItem(CdsAbstract servicesItem) {
+  public CdsServiceInformation addServicesItem(CdsService servicesItem) {
     if (this.services == null) {
       this.services = new ArrayList<>();
     }
@@ -19,11 +19,11 @@ public CdsServiceInformation addServicesItem(CdsAbstract servicesItem) {
     return this;
   }
 
-  public List<CdsAbstract> getServices() {
+  public List<CdsService> getServices() {
     return services;
   }
 
-  public void setServices(List<CdsAbstract> services) {
+  public void setServices(List<CdsService> services) {
     this.services = services;
   }
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceRems.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceRems.java
deleted file mode 100644
index f6e5dbe63..000000000
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceRems.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.hl7.davinci.endpoint.cdshooks.services.crd;
-
-import org.cdshooks.Card;
-import org.cdshooks.CdsRequest;
-import org.cdshooks.CdsResponse;
-import org.cdshooks.Hook;
-import org.hl7.davinci.FhirComponentsT;
-import org.hl7.davinci.PrefetchTemplateElement;
-import org.hl7.davinci.endpoint.components.CardBuilder;
-import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
-import org.hl7.fhir.r4.model.Coding;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-import org.springframework.web.bind.annotation.RequestBody;
-
-import javax.validation.Valid;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-@Component
-public abstract class CdsServiceRems<requestTypeT extends CdsRequest<?, ?>> extends CdsAbstract<requestTypeT> {
-    static final Logger logger = LoggerFactory.getLogger(CdsServiceRems.class);
-
-    public List<Coding> remsDrugs = new ArrayList<>();
-
-    public CdsServiceRems(String id, Hook hook, String title, String description,
-                      List<PrefetchTemplateElement> prefetchElements, FhirComponentsT fhirComponents,
-                      DiscoveryExtension extension) {
-        super(id, hook, title, description, prefetchElements, fhirComponents, extension);
-        Coding turalio = new Coding()
-                .setCode("2183126")
-                .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm")
-                .setDisplay("Turalio");
-        Coding iPledge = new Coding()
-                .setCode("6064")
-                .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm")
-                .setDisplay("Isotretinoin");
-        Coding revlimid = new Coding()
-                .setCode("337535")
-                .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm")
-                .setDisplay("Revlimid");
-        Coding abstral = new Coding()
-                .setCode("1053648")
-                .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm")
-                .setDisplay("Abstral");
-        remsDrugs.add(turalio);
-        remsDrugs.add(iPledge);
-        remsDrugs.add(revlimid);
-        remsDrugs.add(abstral);
-    }
-
-    /**
-     * Performs generic operations for incoming requests of any type.
-     *
-     * @param request the generically typed incoming request
-     * @return The response from the server
-     */
-    public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL applicationBaseUrl) {
-        CdsResponse response = new CdsResponse();
-        List<Coding> medications = getMedications(request);
-        for (Coding medication : medications) {
-            Card card = CardBuilder.summaryCard("");
-            if (isRemsDrug(medication)) {
-                card.setSummary(String.format("%s is a REMS drug", medication.getDisplay()));
-            } else {
-                card.setSummary(String.format("%s is not a REMS drug", medication.getDisplay()));
-            }
-            response.addCard(card);
-        }
-        return response;
-    }
-
-    private boolean isRemsDrug(Coding medication) {
-        for( Coding remsDrug : remsDrugs){
-            if (remsDrug.getCode().equals(medication.getCode())){
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public abstract List<Coding> getMedications(requestTypeT request);
-
-}
\ No newline at end of file
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java
index a5be23692..538169ef9 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java
@@ -18,8 +18,6 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
-import static org.hl7.davinci.endpoint.Utils.idInSelectionsList;
-
 public class FhirBundleProcessor {
   static final Logger logger = LoggerFactory.getLogger(FhirBundleProcessor.class);
 
@@ -50,7 +48,7 @@ public void processDeviceRequests() {
       logger.info("r4/FhirBundleProcessor::getAndProcessDeviceRequests: DeviceRequest(s) found");
 
       for (DeviceRequest deviceRequest : deviceRequestList) {
-        if (idInSelectionsList(deviceRequest.getId(), selections)) {
+        if (idInSelectionsList(deviceRequest.getId())) {
           List<CoverageRequirementRuleCriteria> criteriaList = createCriteriaList(deviceRequest.getCodeCodeableConcept(), deviceRequest.getInsurance(), null);
           buildExecutionContexts(criteriaList, (Patient) deviceRequest.getSubject().getResource(), "device_request", deviceRequest);
         }
@@ -65,7 +63,7 @@ public void processMedicationRequests() {
       logger.info("r4/FhirBundleProcessor::getAndProcessMedicationRequests: MedicationRequest(s) found");
 
       for (MedicationRequest medicationRequest : medicationRequestList) {
-        if (idInSelectionsList(medicationRequest.getId(), selections)) {
+        if (idInSelectionsList(medicationRequest.getId())) {
           List<CoverageRequirementRuleCriteria> criteriaList = createCriteriaList(medicationRequest.getMedicationCodeableConcept(), medicationRequest.getInsurance(), null);
           buildExecutionContexts(criteriaList, (Patient) medicationRequest.getSubject().getResource(), "medication_request", medicationRequest);
         }
@@ -83,7 +81,7 @@ public void processMedicationDispenses() {
           medicationDispenseBundle);
 
       for (MedicationDispense medicationDispense : medicationDispenseList) {
-        if (idInSelectionsList(medicationDispense.getId(), selections)) {
+        if (idInSelectionsList(medicationDispense.getId())) {
           List<CoverageRequirementRuleCriteria> criteriaList = createCriteriaList(medicationDispense.getMedicationCodeableConcept(), null, payorList);
           buildExecutionContexts(criteriaList, (Patient) medicationDispense.getSubject().getResource(), "medication_dispense", medicationDispense);
         }
@@ -98,7 +96,7 @@ public void processServiceRequests() {
       logger.info("r4/FhirBundleProcessor::getAndProcessServiceRequests: ServiceRequest(s) found");
 
       for (ServiceRequest serviceRequest : serviceRequestList) {
-        if (idInSelectionsList(serviceRequest.getId(), selections)) {
+        if (idInSelectionsList(serviceRequest.getId())) {
           List<CoverageRequirementRuleCriteria> criteriaList = createCriteriaList(serviceRequest.getCode(), serviceRequest.getInsurance(), null);
           buildExecutionContexts(criteriaList, (Patient) serviceRequest.getSubject().getResource(), "service_request", serviceRequest);
         }
@@ -118,7 +116,7 @@ public void processOrderSelectMedicationStatements() {
 
       // process each of the MedicationRequests
       for (MedicationRequest medicationRequest : medicationRequestList) {
-        if (idInSelectionsList(medicationRequest.getId(), selections)) {
+        if (idInSelectionsList(medicationRequest.getId())) {
 
           // run on each of the MedicationStatements
           for (MedicationStatement medicationStatement : medicationStatementList) {
@@ -212,4 +210,29 @@ private void buildExecutionContexts(List<CoverageRequirementRuleCriteria> criter
     }
   }
 
+  private String stripResourceType(String identifier) {
+    int indexOfDivider = identifier.indexOf('/');
+    if (indexOfDivider+1 == identifier.length()) {
+      // remove the trailing '/'
+      return identifier.substring(0, indexOfDivider);
+    } else {
+      return identifier.substring(indexOfDivider+1);
+    }
+  }
+
+  private boolean idInSelectionsList(String identifier) {
+    if (this.selections.isEmpty()) {
+      // if selections list is empty, just assume we should process the request
+      return true;
+    } else {
+      for ( String selection : selections) {
+        if (identifier.contains(stripResourceType(selection))) {
+          logger.info("r4/FhirBundleProcessor::idInSelectionsList(" + identifier + "): identifier found in selections list");
+          return true;
+        }
+      }
+      return false;
+    }
+  }
+
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirRequestProcessor.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirRequestProcessor.java
index 3c92f68b3..912b97d8d 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirRequestProcessor.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirRequestProcessor.java
@@ -1,6 +1,7 @@
 package org.hl7.davinci.endpoint.cdshooks.services.crd.r4;
 
 import org.cdshooks.AlternativeTherapy;
+import org.hl7.fhir.instance.model.api.IBase;
 import org.hl7.fhir.instance.model.api.IBaseResource;
 import org.hl7.fhir.r4.model.*;
 import org.slf4j.Logger;
@@ -123,4 +124,44 @@ public static IBaseResource addNoteToRequest(IBaseResource request, Annotation n
 
     return output;
   }
+
+  public static IBaseResource addSupportingInfoToRequest(IBaseResource request, Reference reference) {
+    IBaseResource output = request;
+
+    switch (request.fhirType()) {
+      case "DeviceRequest":
+        DeviceRequest deviceRequest = ((DeviceRequest) request).copy();
+        deviceRequest.addSupportingInfo(reference);
+        output = deviceRequest;
+        break;
+      case "MedicationRequest":
+        MedicationRequest medicationRequest = ((MedicationRequest) request).copy();
+        medicationRequest.addSupportingInformation(reference);
+        output = medicationRequest;
+        break;
+      case "MedicationDispense":
+        MedicationDispense medicationDispense = ((MedicationDispense) request).copy();
+        medicationDispense.addSupportingInformation(reference);
+        output = medicationDispense;
+        break;
+      case "ServiceRequest":
+        ServiceRequest serviceRequest = ((ServiceRequest) request).copy();
+        serviceRequest.addSupportingInfo(reference);
+        output = serviceRequest;
+        break;
+      case "Appointment":
+        Appointment appointment = ((Appointment) request).copy();
+        appointment.addSupportingInformation(reference);
+        output = appointment;
+        break;
+      case "NutritionOrder":
+      case "SupplyRequest":
+      case "Encounter":
+      default:
+        logger.info("Unsupported fhir R4 resource type (" + request.fhirType() + ") when adding note");
+        throw new RuntimeException("Unsupported fhir R4 resource type " + request.fhirType());
+    }
+
+    return output;
+  }
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java
deleted file mode 100644
index a5cf2824b..000000000
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.hl7.davinci.endpoint.cdshooks.services.crd.r4;
-
-import org.cdshooks.Hook;
-import org.hl7.davinci.PrefetchTemplateElement;
-import org.hl7.davinci.endpoint.Utils;
-import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsServiceRems;
-import org.hl7.davinci.r4.FhirComponents;
-import org.hl7.davinci.r4.Utilities;
-import org.hl7.davinci.r4.crdhook.CrdPrefetch;
-import org.hl7.davinci.r4.crdhook.orderselect.CrdPrefetchTemplateElements;
-import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest;
-import org.hl7.fhir.r4.model.Bundle;
-import org.hl7.fhir.r4.model.Coding;
-import org.hl7.fhir.r4.model.MedicationRequest;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-
-@Component("r4_OrderSelectServiceRems")
-public class OrderSelectServiceRems extends CdsServiceRems<OrderSelectRequest> {
-
-    public static final String ID = "order-select-rems";
-    public static final String TITLE = "order-select-rems Coverage Requirements Discovery";
-    public static final Hook HOOK = Hook.ORDER_SELECT;
-    public static final String DESCRIPTION =
-            "Get information regarding the coverage requirements for REMS drugs";
-    public static final List<PrefetchTemplateElement> PREFETCH_ELEMENTS = Arrays.asList(
-            CrdPrefetchTemplateElements.MEDICATION_STATEMENT_BUNDLE,
-            CrdPrefetchTemplateElements.MEDICATION_REQUEST_BUNDLE);
-    public static final FhirComponents FHIRCOMPONENTS = new FhirComponents();
-    static final Logger logger = LoggerFactory.getLogger(OrderSelectServiceRems.class);
-
-    public List<Coding> remsDrugs = new ArrayList<>();
-
-    public OrderSelectServiceRems() {
-        super(ID, HOOK, TITLE, DESCRIPTION, PREFETCH_ELEMENTS, FHIRCOMPONENTS, null);
-    }
-
-
-    public List<Coding> getMedications(OrderSelectRequest request) {
-        List<String> selections = Arrays.asList(request.getContext().getSelections());
-        CrdPrefetch prefetch = request.getPrefetch();
-        List<Coding> medications = getSelections(prefetch, selections);
-        return medications;
-    }
-    public List<Coding> getSelections(CrdPrefetch prefetch, List<String> selections) {
-        Bundle medicationRequestBundle = prefetch.getMedicationRequestBundle();
-        List<MedicationRequest> medicationRequestList = Utilities.getResourcesOfTypeFromBundle(MedicationRequest.class, medicationRequestBundle);
-        List<Coding> codings = new ArrayList<>();
-
-        if (!medicationRequestList.isEmpty()) {
-            for (MedicationRequest medicationRequest : medicationRequestList) {
-                if (Utils.idInSelectionsList(medicationRequest.getId(), selections)) {
-                    codings.add(medicationRequest.getMedicationCodeableConcept().getCodingFirstRep()); // assume there is only 1 coding per MR
-                }
-            }
-        }
-
-        return codings;
-    }
-
-}
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java
index 69ac808be..8b9c7d2ba 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java
@@ -93,6 +93,18 @@ protected CqlResultsForCard executeCqlAndGetRelevantResults(Context context, Str
       logger.info("Prior Auth Required");
       coverageRequirements.setSummary(humanReadableTopic + ": Prior Authorization required.")
           .setDetails("Prior Authorization required, follow the attached link for information.");
+
+      // check if prior auth is automatically approved
+      if (evaluateStatement("APPROVE_PRIORAUTH", context) != null) {
+        coverageRequirements.setPriorAuthApproved((Boolean) evaluateStatement("APPROVE_PRIORAUTH", context));
+        if (coverageRequirements.isPriorAuthApproved()) {
+          coverageRequirements.generatePriorAuthId();
+          logger.info("Prior Auth Approved: " + coverageRequirements.getPriorAuthId());
+          coverageRequirements.setSummary(humanReadableTopic + ": Prior Authorization approved.")
+              .setDetails("Prior Authorization approved, ID is " + coverageRequirements.getPriorAuthId());
+        }
+      }
+
     } else if (coverageRequirements.isDocumentationRequired()) {
       logger.info("Documentation Required");
       coverageRequirements.setSummary(humanReadableTopic + ": Documentation Required.")
@@ -173,6 +185,14 @@ protected CqlResultsForCard executeCqlAndGetRelevantResults(Context context, Str
         logger.info("-- No PA Request questionnaire defined");
       }
 
+      try {
+        if (evaluateStatement("RESULT_QuestionnaireAdditionalUri", context) != null) {
+          coverageRequirements.setQuestionnaireAdditionalUri(evaluateStatement("RESULT_QuestionnaireAdditionalUri", context).toString());
+        }
+      } catch (Exception e) {
+        logger.info("-- No additional questionnaire defined");
+      }
+
       // process the alternative therapies
       try {
         if (evaluateStatement("ALTERNATIVE_THERAPY", context) != null) {
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/components/CardBuilder.java b/server/src/main/java/org/hl7/davinci/endpoint/components/CardBuilder.java
index 92a5633aa..e67ff6f42 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/components/CardBuilder.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/components/CardBuilder.java
@@ -1,18 +1,16 @@
 package org.hl7.davinci.endpoint.components;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
 import org.cdshooks.*;
 import org.hl7.davinci.FhirComponentsT;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.FhirRequestProcessor;
+import org.hl7.davinci.endpoint.database.FhirResource;
+import org.hl7.davinci.endpoint.database.FhirResourceRepository;
+import org.hl7.davinci.r4.Utilities;
 import org.hl7.fhir.instance.model.api.IBase;
 import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.r4.model.Annotation;
-import org.hl7.fhir.r4.model.DeviceRequest;
-import org.hl7.fhir.r4.model.StringType;
+import org.hl7.fhir.r4.model.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -82,21 +80,33 @@ public CqlResultsForCard setRequest(IBaseResource request) {
    * @param cqlResults
    * @return card with appropriate information
    */
-  public static Card transform(CqlResultsForCard cqlResults) {
+  public static Card transform(CqlResultsForCard cqlResults, Boolean addLink) {
     Card card = baseCard();
 
-    Link link = new Link();
-    link.setUrl(cqlResults.getCoverageRequirements().getInfoLink());
-    link.setType("absolute");
-    link.setLabel("Documentation Requirements");
+    if (addLink) {
+      Link link = new Link();
+      link.setUrl(cqlResults.getCoverageRequirements().getInfoLink());
+      link.setType("absolute");
+      link.setLabel("Documentation Requirements");
+      card.setLinks(Arrays.asList(link));
+    }
 
-    card.setLinks(Arrays.asList(link));
     card.setSummary(cqlResults.getCoverageRequirements().getSummary());
     card.setDetail(cqlResults.getCoverageRequirements().getDetails());
 
     return card;
   }
 
+  /**
+   * Transforms a result from the database into a card, defaults to adding the link.
+   *
+   * @param cqlResults
+   * @return card with appropriate information
+   */
+  public static Card transform(CqlResultsForCard cqlResults) {
+    return transform(cqlResults, true);
+  }
+
   /**
    * Transforms a result from the database into a card.
    *
@@ -180,6 +190,8 @@ public static Card alternativeTherapyCard(AlternativeTherapy alternativeTherapy,
     suggestionList.add(alternativeTherapySuggestion);
     card.setSuggestions(suggestionList);
 
+    card.setSelectionBehavior(Card.SelectionBehaviorEnum.ANY);
+
     return card;
   }
 
@@ -192,14 +204,90 @@ public static Card drugInteractionCard(DrugInteraction drugInteraction) {
     return card;
   }
 
-  public static Card createSuggestionsWithNote(Card card,
-                                               CqlResultsForCard cqlResults,
-                                               FhirComponentsT fhirComponents) {
-    List<Suggestion> suggestionList = new ArrayList<>();
+  public static Card priorAuthCard(CqlResultsForCard cqlResults,
+                                   IBaseResource request,
+                                   FhirComponentsT fhirComponents,
+                                   String priorAuthId,
+                                   String patientId,
+                                   String payerId,
+                                   String providerId,
+                                   String applicationFhirPath,
+                                   FhirResourceRepository fhirResourceRepository) {
+    logger.info("Build Prior Auth Card");
+
+    Card card = transform(cqlResults, false);
+
+    // create the ClaimResponse
+    ClaimResponse claimResponse = Utilities.createClaimResponse(priorAuthId, patientId, payerId, providerId, applicationFhirPath);
+
+    // build the FhirResource and save to the database
+    FhirResource fhirResource = new FhirResource();
+    fhirResource.setFhirVersion(fhirComponents.getFhirVersion().toString())
+        .setResourceType(claimResponse.fhirType())
+        .setData(fhirComponents.getJsonParser().encodeResourceToString(claimResponse));
+    fhirResource.setId(claimResponse.getId());
+    fhirResource.setName(claimResponse.getId());
+    FhirResource newFhirResource = fhirResourceRepository.save(fhirResource);
+    logger.info("stored: " + newFhirResource.getFhirVersion() + "/" + newFhirResource.getResourceType() + "/" + newFhirResource.getId());
+
+    // create the reference to the ClaimResponse
+    Reference claimResponseReference = new Reference();
+    claimResponseReference.setReference("ClaimResponse/" + claimResponse.getId());
+
+    // add SupportingInfo to the Request
+    IBaseResource outputRequest = FhirRequestProcessor.addSupportingInfoToRequest(request, claimResponseReference);
+
+    // add suggestion with ClaimResponse
+    Suggestion suggestionWithClaimResponse = createSuggestionWithResource(outputRequest, claimResponse, fhirComponents,
+        "Store the prior authorization in the EHR");
+    card.addSuggestionsItem(suggestionWithClaimResponse);
+
+    // add suggestion with annotation
+    Suggestion suggestionWithAnnotation = createSuggestionWithNote(card, outputRequest, fhirComponents,
+        "Store prior authorization as an annotation to the order", "Add authorization to record",
+        false);
+    card.addSuggestionsItem(suggestionWithAnnotation);
+
+    card.setSelectionBehavior(Card.SelectionBehaviorEnum.AT_MOST_ONE);
+
+    return card;
+  }
+
+  public static Suggestion createSuggestionWithResource(IBaseResource request,
+                                                        IBaseResource resource,
+                                                        FhirComponentsT fhirComponents,
+                                                        String label) {
+    Suggestion suggestion = new Suggestion();
+
+    suggestion.setLabel(label);
+    suggestion.setIsRecommended(true);
+
+    // build the create Action
+    Action createAction = new Action(fhirComponents);
+    createAction.setType(Action.TypeEnum.create);
+    createAction.setDescription("Store " + resource.fhirType());
+    createAction.setResource(resource);
+    suggestion.addActionsItem(createAction);
+
+    // build the update Action
+    Action updateAction = new Action(fhirComponents);
+    updateAction.setType(Action.TypeEnum.update);
+    updateAction.setDescription("Update to the resource " + request.fhirType());
+    updateAction.setResource(request);
+    suggestion.addActionsItem(updateAction);
+
+    return suggestion;
+  }
+  public static Suggestion createSuggestionWithNote(Card card,
+                                                    IBaseResource request,
+                                                    FhirComponentsT fhirComponents,
+                                                    String label,
+                                                    String description,
+                                                    boolean isRecommended) {
     Suggestion requestWithNoteSuggestion = new Suggestion();
 
-    requestWithNoteSuggestion.setLabel("Save Update To EHR");
-    requestWithNoteSuggestion.setIsRecommended(true);
+    requestWithNoteSuggestion.setLabel(label);
+    requestWithNoteSuggestion.setIsRecommended(isRecommended);
     List<Action> actionList = new ArrayList<>();
 
     // build the Annotation
@@ -210,19 +298,17 @@ public static Card createSuggestionsWithNote(Card card,
     String text = card.getSummary() + ": " + card.getDetail();
     annotation.setText(text);
     annotation.setTime(new Date()); // set the date and time to now
-    IBaseResource resource = FhirRequestProcessor.addNoteToRequest(cqlResults.getRequest(), annotation);
+    IBaseResource resource = FhirRequestProcessor.addNoteToRequest(request, annotation);
 
     Action updateAction = new Action(fhirComponents);
     updateAction.setType(Action.TypeEnum.update);
-    updateAction.setDescription("Update original " + cqlResults.getRequest().fhirType() + " to add note");
+    updateAction.setDescription(description);
     updateAction.setResource(resource);
 
     actionList.add(updateAction);
 
     requestWithNoteSuggestion.setActions(actionList);
-    suggestionList.add(requestWithNoteSuggestion);
-    card.setSuggestions(suggestionList);
-    return card;
+    return requestWithNoteSuggestion;
   }
 
   /**
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/controllers/QuestionnaireController.java b/server/src/main/java/org/hl7/davinci/endpoint/controllers/QuestionnaireController.java
new file mode 100644
index 000000000..ea583a748
--- /dev/null
+++ b/server/src/main/java/org/hl7/davinci/endpoint/controllers/QuestionnaireController.java
@@ -0,0 +1,409 @@
+package org.hl7.davinci.endpoint.controllers;
+
+import org.hl7.davinci.endpoint.Application;
+import org.hl7.davinci.endpoint.files.FileResource;
+import org.hl7.davinci.endpoint.files.FileStore;
+import org.hl7.fhir.instance.model.api.IDomainResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import org.hl7.davinci.r4.FhirComponents;
+
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.hl7.fhir.r4.model.Questionnaire;
+import org.hl7.fhir.r4.model.QuestionnaireResponse;
+import org.hl7.fhir.r4.model.Resource;
+import org.hl7.fhir.r4.model.ResourceType;
+import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemAnswerOptionComponent;
+import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent;
+import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent;
+import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemComponent;
+import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseStatus;
+import org.hl7.fhir.r4.model.Reference;
+
+// --- ORDER OF RESPONSE-REQUEST OPERATIONS
+// (REQUEST) External user sends the initial QuestionnaireResponse JSON that contains which questionnaire it would like to trigger as n element the "contained" field.
+// (RESPONSE) QuestionnaireController adds the first question with its answerResponse options (with its linkId and text) to the JSON in QuestionnaireResponse.contained.item[] and sends it back.
+// (REQUEST) External user adds their answer to the question to the JSON in QuestionnaireResponse.item[] and sends it back.
+// (RESPONSE) QuestionnaireController takes that response and adds the next indicated question to the JSON in QuestionnaireResponse.contained.item[] and sends it back.
+// Repeat intil QuestionnaireController reaches a leaf-node, then it sets the status to "completed" from "in-progress"
+// Ultimately, The QuestionnaireController responses add ONLY to the QuestionnaireResponse.contained.item[]. The external requester adds answers to QuestionnaireResponse.item[] and includes the associated linkid and text.
+
+@CrossOrigin
+@RestController
+@RequestMapping("/Questionnaire")
+public class QuestionnaireController {
+
+    @Autowired
+    private FileStore fileStore;
+
+    /**
+     * An inner class that demos a tree to define next questions based on responses.
+     */
+    private class AdaptiveQuestionnaireTree {
+        
+        // The initial question node of the tree.
+        private AdaptiveQuestionnaireNode root;
+    
+        /**
+         * Initial constructor that generates the beginning of the tree.
+         * @param inputQuestionnaire    The input questionnaire from the CDS-Library.
+         */
+        public AdaptiveQuestionnaireTree(Questionnaire inputQuestionnaire) {
+            // Top level parent question item; the first set of questions.
+            QuestionnaireItemComponent topLevelQuestion = inputQuestionnaire.getItemFirstRep();
+            // Start the root building.
+            this.root = new AdaptiveQuestionnaireNode(topLevelQuestion);
+        }
+
+        /**
+         * Returns the next question based on the response to the current question. Also sets the next question based on that response.
+         * @param inputQuestionnaireResponse
+         * @param allAnswerItems  The set of answer items given to this tree.
+         * @return
+         */
+        public List<QuestionnaireItemComponent> getNextQuestionsForAnswers(List<QuestionnaireResponseItemComponent> allResponseItems, QuestionnaireResponse inputQuestionnaireResponse) {
+            if(allResponseItems == null) {
+                throw new NullPointerException("Input answer items is null.");
+            } else if ((new HashSet(allResponseItems.stream().map(item -> item.getLinkId()).collect(Collectors.toList()))).size() != allResponseItems.size()){
+                throw new RuntimeException("Detected duplicate answers to the same question.");
+            }
+            return this.root.getNextQuestionForAnswers(allResponseItems, inputQuestionnaireResponse);
+        }
+    
+        /**
+         * Inner class that describes a node of the tree.
+         */
+        private class AdaptiveQuestionnaireNode {
+
+            // Contains the list of additional questions that should be displayed with this question.
+            private List<QuestionnaireItemComponent> supplementalQuestions;
+            // Contains the current question item that dictates the next question of the node.
+            private QuestionnaireItemComponent determinantQuestionItem;
+            // Map of (answerResponse->childQuestionItemNode) (The child could have answer options within it or be a leaf node. It does have a question item component though).
+            private Map<String, AdaptiveQuestionnaireNode> children;
+
+            /**
+             * Constructor
+             * @param determinantQuestionItem
+             */
+            public AdaptiveQuestionnaireNode(QuestionnaireItemComponent determinantQuestion) {
+
+                this.determinantQuestionItem = determinantQuestion;
+                // Get the child and supplemental question items of this question.
+                List<QuestionnaireItemComponent> subQuestions = determinantQuestion.getItem();
+                // Extract the supplemental questions which do not have a child link-id branch from the determinant questions.
+                List<String> nonSupplementLinkIds = determinantQuestionItem.getAnswerOption().stream().map(answerOption -> answerOption.getModifierExtensionFirstRep().getUrl()).collect(Collectors.toList());
+                List<QuestionnaireItemComponent> childQuestions = this.extractChildQuestions(subQuestions, nonSupplementLinkIds);
+                // Extract the remaining questions as supplemental questions.
+                this.supplementalQuestions = this.extractSupplementalQuestions(subQuestions, nonSupplementLinkIds);
+
+                // The number of answer options of the determinant question should always equal the number of child question items.
+                if((this.determinantQuestionItem.getAnswerOption().size() != childQuestions.size())){
+                    throw new RuntimeException("There should be the same number of answer options as sub-items. Answer options: " + this.determinantQuestionItem.getAnswerOption().size() + ", sub-items: " + childQuestions.size());
+                }
+
+                // If the determinant question item does not have any answer options, then this is a leaf node and should not generate any children.
+                if(determinantQuestionItem.hasAnswerOption()) {
+                    Map<String, String> childIdsToResponses = new HashMap<String, String>();
+                    // This loop iterates over the possible answer options of this questionitem and links the linkId to its possible responses.
+                    for(QuestionnaireItemAnswerOptionComponent answerOption : determinantQuestionItem.getAnswerOption()) {
+                        // The Id of this answer response's next question.
+                        String answerNextQuestionId = answerOption.getModifierExtensionFirstRep().getUrl();
+                        // The response that indicates this answer to the question.
+                        String possibleAnswerResponse = answerOption.getValueCoding().getCode();
+                        // Check for issues.
+                        if(answerNextQuestionId == null || possibleAnswerResponse == null){
+                            throw new RuntimeException("Malformed Adaptive Questionnaire. Missing a question ID or answer response.");
+                        }
+                        // Add the key-value pair of next question id to its assocated answer response.
+                        childIdsToResponses.put(answerNextQuestionId, possibleAnswerResponse);
+                    }
+
+                    // Create the map of answerResponses->subQuestionItems
+                    this.children = new HashMap<String, AdaptiveQuestionnaireNode>();
+                    List<QuestionnaireItemComponent> subQuestionItems = determinantQuestionItem.getItem();
+                    for(QuestionnaireItemComponent subQuestionItem : subQuestionItems){
+                        // SubQuestion linkId.
+                        String subQuestionLinkId = subQuestionItem.getLinkId();
+                        // SubQuestion's associated response.
+                        String subQuestionResponse = childIdsToResponses.get(subQuestionLinkId);
+                        // Create a new node for this subQuestion.
+                        AdaptiveQuestionnaireNode subQuestionNode = new AdaptiveQuestionnaireNode(subQuestionItem);
+                        this.children.put(subQuestionResponse, subQuestionNode);
+                    }
+                }
+            }
+
+            /**
+             * Returns the next question based on the set of provided answers.
+             * @param allResponseItems
+             * @param inputQuestionnaireResponse
+             * @return
+             */
+            public List<QuestionnaireItemComponent> getNextQuestionForAnswers(List<QuestionnaireResponseItemComponent> allResponseItems, QuestionnaireResponse inputQuestionnaireResponse) {
+
+                // Extract the current question being answered from the list if answer items.
+                String currentQuestionId = this.determinantQuestionItem.getLinkId();
+                List<QuestionnaireResponseItemComponent> currentQuestionResponses = allResponseItems.stream().filter(answerItem -> answerItem.getLinkId().equals(currentQuestionId)).collect(Collectors.toList());
+                if(currentQuestionResponses.size() != 1) {
+                    // If there are no more answer items to check, we've reached the end of the recursion.
+                    // TODO - this could cause an unexpected end-of-questionnaire issue if incorrect responses are given.
+                    return this.getQuestionSet();
+                }
+
+                QuestionnaireResponseItemComponent currentQuestionResponse = currentQuestionResponses.get(0);
+                QuestionnaireResponseItemAnswerComponent currentQuestionAnswer = currentQuestionResponse.getAnswerFirstRep();
+
+                // With the currrent question answer in hand, extract the next question.
+                String response;
+                if (currentQuestionAnswer.hasValueStringType()) {
+                    response = currentQuestionAnswer.getValueStringType().asStringValue();
+                } else if (currentQuestionAnswer.hasValueCoding()) {
+                    response = currentQuestionAnswer.getValueCoding().getCode();
+                } else {
+                    throw new RuntimeException("Answer does not match one of the possible input types.");
+                }
+                if(!children.containsKey(response)){
+                    throw new NullPointerException("Response does not match with a possible next question.");
+                }
+                AdaptiveQuestionnaireNode nextNode = this.children.get(response);
+
+                if(nextNode.isLeafNode()){
+                    // Since the next node is a leaf node, set the questionnaire response status to complete.
+                    inputQuestionnaireResponse.setStatus(QuestionnaireResponseStatus.COMPLETED);
+                    return nextNode.getQuestionSet();
+                }
+                
+                // Has to be done this way without removing the previous answer response so that we don't alter the original list object.
+                List<QuestionnaireResponseItemComponent> nextResponseItems = allResponseItems.stream().filter(responseItem -> !responseItem.equals(currentQuestionResponse)).collect(Collectors.toList());
+                return nextNode.getNextQuestionForAnswers(nextResponseItems, inputQuestionnaireResponse);
+            }
+
+            /**
+             * Returns the question items in the given list that do not have the linkids of the given list of strings.
+             * @param questionItems
+             * @param nonSupplementQuestions
+             * @return
+             */
+            private List<QuestionnaireItemComponent> extractSupplementalQuestions(
+                    List<QuestionnaireItemComponent> questionItems, List<String> nonSupplementLinkIds) {
+                return questionItems.stream().filter(questionItem -> !nonSupplementLinkIds.contains(questionItem.getLinkId())).collect(Collectors.toList());
+            }
+
+            /**
+             * Returns the question items in the given list that do have the linkids of the given list of strings.
+             * @param questionItems
+             * @param nonSupplementQuestions
+             * @return
+             */
+            private List<QuestionnaireItemComponent> extractChildQuestions(
+                    List<QuestionnaireItemComponent> questionItems, List<String> nonSupplementLinkIds) {
+                return questionItems.stream().filter(questionItem -> nonSupplementLinkIds.contains(questionItem.getLinkId())).collect(Collectors.toList());
+            }
+
+            /**
+             * Returns the set of questions associated with the node. Incldues all questions in the set, determinant and non-determinant.
+             * @return
+             */
+            public List<QuestionnaireItemComponent> getQuestionSet() {
+                QuestionnaireItemComponent determinantQuestionNoChildren = this.removeChildrenFromQuestionItem(this.determinantQuestionItem);
+                List<QuestionnaireItemComponent> questionSet = new ArrayList<QuestionnaireItemComponent>();
+                questionSet.add(determinantQuestionNoChildren);
+                questionSet.addAll(this.supplementalQuestions);
+                logger.info("--- Question Set: " + questionSet.stream().map(item -> item.getLinkId()).collect(Collectors.toList()));
+                return questionSet;
+            }
+
+            /**
+             * Returns a new question item that is indentical to the input qusetion item except without the children.
+             * @param inputQuestionItem
+             * @return
+             */
+            private QuestionnaireItemComponent removeChildrenFromQuestionItem(QuestionnaireItemComponent inputQuestionItem){
+                QuestionnaireItemComponent questionItemNoChildren = new QuestionnaireItemComponent();
+                questionItemNoChildren.setLinkId(inputQuestionItem.getLinkId());
+                questionItemNoChildren.setText(inputQuestionItem.getText());
+                questionItemNoChildren.setType(inputQuestionItem.getType());
+                questionItemNoChildren.setRequired(inputQuestionItem.getRequired());
+                questionItemNoChildren.setAnswerOption(inputQuestionItem.getAnswerOption());
+                return questionItemNoChildren;
+            }
+
+            /**
+             * Returns whether this questionniare is a leaf node.
+             * @return
+             */
+            private boolean isLeafNode() {
+                return this.children == null || this.children.size() < 1;
+            }
+        }
+    }
+
+    // Logger.
+    private static Logger logger = Logger.getLogger(Application.class.getName());
+    // Trees that track the current and next questions. Is key-value mappng of: Map<Questionnaire ID -> AdaptiveQuestionnaireTree>
+    private static final Map<String, AdaptiveQuestionnaireTree> questionnaireTrees = new HashMap<String, AdaptiveQuestionnaireTree>();
+
+    /**
+     * Retrieves the next question based on the request.
+     * @param request
+     * @param entity
+     * @return
+     */
+    @PostMapping(value = "/$next-question", consumes = { MediaType.APPLICATION_JSON_VALUE, "application/fhir+json" })
+    public ResponseEntity<String> retrieveNextQuestion(HttpServletRequest request, HttpEntity<String> entity) {
+        return getNextQuestionOperation(entity.getBody(), request);
+    }
+
+    /**
+     * Returns the next question based on the request.
+     * @param body
+     * @param request
+     * @return
+     */
+    private ResponseEntity<String> getNextQuestionOperation(String body, HttpServletRequest request) {
+        logger.info("POST /Questionnaire/$next-question fhir+");
+
+        FhirContext ctx = new FhirComponents().getFhirContext();
+        IParser parser = ctx.newJsonParser();
+
+        // Parses the body.
+        IDomainResource domainResource = (IDomainResource) parser.parseResource(QuestionnaireResponse.class, body);
+        if (!domainResource.fhirType().equalsIgnoreCase("QuestionnaireResponse")) {
+            logger.warning("unsupported resource type: ");
+            HttpStatus status = HttpStatus.BAD_REQUEST;
+            MediaType contentType = MediaType.TEXT_PLAIN;
+            return ResponseEntity.status(status).contentType(contentType).body("Bad Request");
+        } else {
+            logger.info(" ---- Resource received " + domainResource.toString());
+            QuestionnaireResponse inputQuestionnaireResponse = (QuestionnaireResponse) domainResource;
+            String fragmentId = inputQuestionnaireResponse.getQuestionnaire();
+            List<Resource> containedResource = inputQuestionnaireResponse.getContained();
+            Questionnaire inputQuestionnaireFromRequest = null;
+            for (int i = 0; i < containedResource.size(); i++) {
+                Resource item = containedResource.get(i);
+                if (item.getResourceType().equals(ResourceType.Questionnaire)) {
+                    Questionnaire checkInputQuestionnaire = (Questionnaire) item;
+                    if (checkInputQuestionnaire.getId().equals(fragmentId)) {
+                        inputQuestionnaireFromRequest = checkInputQuestionnaire;
+                        break;
+                    }
+                }
+            }
+
+            logger.info("--- Received questionnaire response: " + ctx.newJsonParser().encodeResourceToString(inputQuestionnaireResponse));
+            // Check that there are no duplicates in the recieved set of questions.
+            if ((new HashSet(((Questionnaire) inputQuestionnaireResponse.getContained().get(0)).getItem().stream().map(item -> item.getLinkId()).collect(Collectors.toList()))).size() != ((Questionnaire) inputQuestionnaireResponse.getContained().get(0)).getItem().size()){
+                throw new RuntimeException("Received a set of questions with duplicates.");
+            }
+
+            String questionnaireId = ((Reference) inputQuestionnaireResponse.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/contained-id").getValue()).getReference();
+            System.out.println("Input Questionnaire: " + questionnaireId);
+
+            if (inputQuestionnaireFromRequest != null) {
+
+                if (!questionnaireTrees.containsKey(questionnaireId)) {
+                    // If there is not already a tree that matches the requested questionnaire id, build it.
+                    // Import the requested CDS-Library Questionnaire.
+                    Questionnaire cdsQuestionnaire = QuestionnaireController.importCdsAdaptiveQuestionnaire(request, parser, fileStore, questionnaireId);
+                    
+                    // Build the tree.
+                    AdaptiveQuestionnaireTree newTree = new AdaptiveQuestionnaireTree(cdsQuestionnaire);
+                    questionnaireTrees.put(questionnaireId, newTree);
+                    logger.info("--- Built Questionnaire Tree for " + questionnaireId);
+                }
+
+                // Pull the tree for the requested questionnaire id.
+                AdaptiveQuestionnaireTree currentTree = questionnaireTrees.get(questionnaireId);
+                // Get the request's set of answer responses.
+                List<QuestionnaireResponseItemComponent> allResponses = inputQuestionnaireResponse.getItem();
+                // Pull the resulting next question that the recieved responses and answers point to from the tree without including its children.
+                List<QuestionnaireItemComponent> nextQuestionSetResults = currentTree.getNextQuestionsForAnswers(allResponses, inputQuestionnaireResponse);
+                // Add the next set of questions to the response.
+                QuestionnaireController.addQuestionSetToQuestionnaireResponse(inputQuestionnaireResponse, nextQuestionSetResults);
+                // Check that there no duplicates in the set of questions.
+                if ((new HashSet(((Questionnaire) inputQuestionnaireResponse.getContained().get(0)).getItem().stream().map(item -> item.getLinkId()).collect(Collectors.toList()))).size() != ((Questionnaire) inputQuestionnaireResponse.getContained().get(0)).getItem().size()){
+                    throw new RuntimeException("Attempted to send a set of questions with duplicates. Question IDs are: " + (((Questionnaire) inputQuestionnaireResponse.getContained().get(0)).getItem().stream().map(item -> item.getLinkId()).collect(Collectors.toList())));
+                }
+
+                logger.info("--- Added next question set for questionnaire \'" + questionnaireId + "\' for responses \'" + allResponses + "\'.");
+
+                // Build and send the response.
+                String formattedResourceString = ctx.newJsonParser().encodeResourceToString(inputQuestionnaireResponse);
+                logger.info("--- Sending questionnaire response: " + formattedResourceString);
+                return ResponseEntity.status(HttpStatus.ACCEPTED).contentType(MediaType.APPLICATION_JSON)
+                        .header(HttpHeaders.CONTENT_TYPE, "application/fhir+json" + "; charset=utf-8")
+                        .body(formattedResourceString);
+            } else {
+                return ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON)
+                        .header(HttpHeaders.CONTENT_TYPE, "application/fhir+json" + "; charset=utf-8")
+                        .body("Input questionnaire from the request does not exist.");
+            }
+        }
+    }
+
+    /**
+     * Imports the requested questionnaire from the CDS-Library.
+     * @param fileStore2
+     * @param parser
+     * @param request
+     * @return
+     */
+    private static Questionnaire importCdsAdaptiveQuestionnaire(HttpServletRequest request, IParser parser, FileStore fileStore, String questionnaireId) {
+        Questionnaire cdsQuestionnaire = null;
+        try {
+            String adaptiveQuestionniareFile = ("Questions-" + questionnaireId + "Adaptive.json").replace("#", ""); // The filename should be the questionnaire ID with these added values.
+            String topic = questionnaireId.replace("Additional", "").replace("#", ""); // The topic should be the questionnaire ID but without the 'Additional' tag.
+            // File is pulled from the file store as a file.
+            logger.info("--- Importing questionniare file: " + adaptiveQuestionniareFile + " from topic: " + topic);
+            FileResource fileResource = fileStore.getFile(topic, adaptiveQuestionniareFile, "R4", false);
+            if(fileResource == null) {
+                throw new RuntimeException("File resource pulled from the filestore is null.");
+            }
+            if(fileResource.getResource() == null) {
+                throw new RuntimeException("File resource pulled from the filestore has a null getResource().");
+            }
+            cdsQuestionnaire = (Questionnaire) parser.parseResource(fileResource.getResource().getInputStream());
+            logger.info("--- Imported Questionnaire " + cdsQuestionnaire.getId());
+        } catch (DataFormatException e) {
+            e.printStackTrace();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return cdsQuestionnaire;
+    }
+
+    /**
+     * Adds the given set of questions to the contained questionniare in the questionnaire response.
+     * @param inputQuestionnaireResponse
+     * @param questionSet
+     */
+    private static void addQuestionSetToQuestionnaireResponse(QuestionnaireResponse inputQuestionnaireResponse, List<QuestionnaireItemComponent> questionSet) {
+        // Add the next question set to the QuestionnaireResponse.contained[0].item[].
+        Questionnaire containedQuestionnaire = (Questionnaire) inputQuestionnaireResponse.getContained().get(0);
+        questionSet.forEach(questionItem -> containedQuestionnaire.addItem(questionItem));
+    }
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java b/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java
index b3afdfcc3..cb4ea5be6 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java
@@ -1,10 +1,11 @@
 package org.hl7.davinci.endpoint.controllers.r4;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
 import org.cdshooks.CdsResponse;
 import org.hl7.davinci.endpoint.Utils;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsServiceInformation;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.OrderSelectService;
-import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.OrderSelectServiceRems;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.OrderSignService;
 import org.hl7.davinci.r4.crdhook.CrdPrefetch;
 import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest;
@@ -12,10 +13,14 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.validation.Valid;
+import java.io.IOException;
+import java.util.stream.Collectors;
 
 @RestController("r4_CdsHooksController")
 public class CdsHooksController {
@@ -28,7 +33,7 @@ public class CdsHooksController {
 
   @Autowired private OrderSelectService orderSelectService;
   @Autowired private OrderSignService orderSignService;
-  @Autowired private OrderSelectServiceRems orderSelectServiceRems;
+
   /**
    * The FHIR r4 services discovery endpoint.
    * @return A services object containing an array of all services available on this server
@@ -59,21 +64,6 @@ public CdsResponse handleOrderSelect(@Valid @RequestBody OrderSelectRequest requ
     return orderSelectService.handleRequest(request, Utils.getApplicationBaseUrl(httpServletRequest));
   }
 
-  /**
-   * The coverage requirement discovery endpoint for the order select rems hook.
-   * @param request An order select triggered cds request
-   * @return The card response
-   */
-  @CrossOrigin
-  @PostMapping(value = FHIR_RELEASE + URL_BASE + "/" + OrderSelectServiceRems.ID,
-          consumes = "application/json;charset=UTF-8")
-  public CdsResponse handleOrderSelectRems(@Valid @RequestBody OrderSelectRequest request, final HttpServletRequest httpServletRequest) {
-    logger.info("r4/handleOrderSelectRems");
-    if (request.getPrefetch() == null) {
-      request.setPrefetch(new CrdPrefetch());
-    }
-    return orderSelectServiceRems.handleRequest(request, Utils.getApplicationBaseUrl(httpServletRequest));
-  }
   /**
    * The coverage requirement discovery endpoint for the order sign hook.
    * @param request An order sign triggered cds request
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceCriteria.java b/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceCriteria.java
index ce1ccd6fa..08f8e50af 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceCriteria.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceCriteria.java
@@ -2,11 +2,11 @@
 
 public class FhirResourceCriteria {
 
-  private String fhirVersion;
-  private String resourceType;
-  private String name;
-  private String id;
-  private String url;
+  private String fhirVersion = null;
+  private String resourceType = null;
+  private String name = null;
+  private String id = null;
+  private String url = null;
 
   public String getFhirVersion() { return fhirVersion; }
 
@@ -44,8 +44,52 @@ public FhirResourceCriteria setUrl(String url) {
   }
 
   public String toString() {
-    return String.format(
-        "fhirVersion=%s, resourceType=%s, name=%s", fhirVersion, resourceType, name
-    );
+    String string = new String();
+    boolean first = true;
+    if (fhirVersion != null) {
+      if (first) {
+        first = false;
+      } else {
+        string = string + ", ";
+      }
+      string = string + "fhirVersion=" + fhirVersion;
+    }
+
+    if (resourceType != null) {
+      if (first) {
+        first = false;
+      } else {
+        string = string + ", ";
+      }
+      string = string + "resourceType=" + resourceType;
+    }
+
+    if (id != null) {
+      if (first) {
+        first = false;
+      } else {
+        string = string + ", ";
+      }
+      string = string + "id=" + id;
+    }
+
+    if (name != null) {
+      if (first) {
+        first = false;
+      } else {
+        string = string + ", ";
+      }
+      string = string + "name=" + name;
+    }
+
+    if (url != null) {
+      if (first) {
+        first = false;
+      } else {
+        string = string + ", ";
+      }
+      string = string + "url=" + url;
+    }
+    return string;
   }
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceRepository.java b/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceRepository.java
index adacc77e9..5d01a8a0f 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceRepository.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/database/FhirResourceRepository.java
@@ -17,7 +17,7 @@ public interface FhirResourceRepository extends CrudRepository<FhirResource, Lon
   @Query(
       "SELECT r FROM FhirResource r WHERE "
           + "r.fhirVersion = :#{#criteria.fhirVersion} "
-          + "and r.resourceType = :#{#criteria.resourceType} "
+          + "and LOWER(r.resourceType) = :#{#criteria.resourceType} "
           + "and r.id = :#{#criteria.id}")
   List<FhirResource> findById(
       @Param("criteria") FhirResourceCriteria criteria
@@ -26,7 +26,7 @@ List<FhirResource> findById(
   @Query(
       "SELECT r FROM FhirResource r WHERE "
           + "r.fhirVersion = :#{#criteria.fhirVersion} "
-          + "and r.resourceType = :#{#criteria.resourceType} "
+          + "and LOWER(r.resourceType) = :#{#criteria.resourceType} "
           + "and r.name = :#{#criteria.name}")
   List<FhirResource> findByName(
       @Param("criteria") FhirResourceCriteria criteria
@@ -35,7 +35,7 @@ List<FhirResource> findByName(
   @Query(
       "SELECT r FROM FhirResource r WHERE "
           + "r.fhirVersion = :#{#criteria.fhirVersion} "
-          + "and r.resourceType = :#{#criteria.resourceType} "
+          + "and LOWER(r.resourceType) = :#{#criteria.resourceType} "
           + "and r.url = :#{#criteria.url}")
   List<FhirResource> findByUrl(
       @Param("criteria") FhirResourceCriteria criteria
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/files/CommonFileStore.java b/server/src/main/java/org/hl7/davinci/endpoint/files/CommonFileStore.java
index a10381674..a0b52c5ed 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/files/CommonFileStore.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/files/CommonFileStore.java
@@ -21,6 +21,7 @@
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.util.List;
+import java.util.Locale;
 
 public abstract class CommonFileStore implements FileStore {
 
@@ -101,10 +102,10 @@ protected FileResource readFhirResourceFromFiles(List<FhirResource> fhirResource
   }
 
   public FileResource getFhirResourceByTopic(String fhirVersion, String resourceType, String name, String baseUrl) {
-    logger.info("CommonFileStore::getFhirResourceByTopic(): " + fhirVersion + "/" + resourceType + "/" + name);
-
     FhirResourceCriteria criteria = new FhirResourceCriteria();
-    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType).setName(name);
+    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType.toLowerCase()).setName(name);
+    logger.info("CommonFileStore::getFhirResourceByTopic(): " + criteria.toString());
+
     List<FhirResource> fhirResourceList = fhirResources.findByName(criteria);
     FileResource resource = readFhirResourceFromFiles(fhirResourceList, fhirVersion, baseUrl);
 
@@ -125,12 +126,13 @@ public FileResource getFhirResourceById(String fhirVersion, String resourceType,
 
   public FileResource getFhirResourceById(String fhirVersion, String resourceType, String id, String baseUrl,
       boolean isRoot) {
-    logger.info("CommonFileStore::getFhirResourceById(): " + fhirVersion + "/" + resourceType + "/" + id);
-
     FhirResourceCriteria criteria = new FhirResourceCriteria();
-    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType).setId(id);
+    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType.toLowerCase()).setId(id);
+    logger.info("CommonFileStore::getFhirResourceById(): " + criteria.toString());
+
     List<FhirResource> fhirResourceList = fhirResources.findById(criteria);
     FileResource resource = readFhirResourceFromFiles(fhirResourceList, fhirVersion, baseUrl);
+    System.out.println("Resource Pulled: " + resource + "-" + resource.getFilename());
 
     if ((resource != null) && fhirVersion.equalsIgnoreCase("r4")) {
 
@@ -153,10 +155,10 @@ public FileResource getFhirResourceById(String fhirVersion, String resourceType,
   }
 
   public FileResource getFhirResourceByUrl(String fhirVersion, String resourceType, String url, String baseUrl) {
-    logger.info("CommonFileStore::getFhirResourceByUrl(): " + fhirVersion + "/" + resourceType + "/" + url);
-
     FhirResourceCriteria criteria = new FhirResourceCriteria();
-    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType).setUrl(url);
+    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType.toLowerCase()).setUrl(url);
+    logger.info("CommonFileStore::getFhirResourceByUrl(): " + criteria.toString());
+
     List<FhirResource> fhirResourceList = fhirResources.findByUrl(criteria);
     FileResource resource = readFhirResourceFromFiles(fhirResourceList, fhirVersion, baseUrl);
 
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/files/SubQuestionnaireProcessor.java b/server/src/main/java/org/hl7/davinci/endpoint/files/SubQuestionnaireProcessor.java
index f4fcf781b..a5b9adbb6 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/files/SubQuestionnaireProcessor.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/files/SubQuestionnaireProcessor.java
@@ -8,12 +8,9 @@
 import org.hl7.fhir.r4.model.CanonicalType;
 import org.hl7.fhir.r4.model.Extension;
 import org.hl7.fhir.r4.model.Questionnaire;
-import org.hl7.fhir.r4.model.Reference;
-import org.hl7.fhir.r4.model.ValueSet;
 import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.hl7.fhir.r4.model.Resource;
 
 /**
  * Processes FHIR R4 questionnaire to assemble sub-questionnaires into a complete questionnaire.
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rules/CoverageRequirementRuleCriteria.java b/server/src/main/java/org/hl7/davinci/endpoint/rules/CoverageRequirementRuleCriteria.java
index e630a7bad..b6728f847 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rules/CoverageRequirementRuleCriteria.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rules/CoverageRequirementRuleCriteria.java
@@ -8,6 +8,7 @@
 public class CoverageRequirementRuleCriteria {
 
   private String payor;
+  private String payorId;
   private String code;
   private String codeSystem;
   private String fhirVersion;
@@ -45,6 +46,13 @@ public CoverageRequirementRuleCriteria setPayor(String payor) {
     return this;
   }
 
+  public String getPayorId() { return payorId; }
+
+  public CoverageRequirementRuleCriteria setPayorId(String payorId) {
+    this.payorId = payorId;
+    return this;
+  }
+
   public String getFhirVersion() { return fhirVersion; }
 
   public CoverageRequirementRuleCriteria setFhirVersion(String fhirVersion) {
@@ -71,8 +79,9 @@ public static List<CoverageRequirementRuleCriteria> createQueriesFromR4(List<org
       String codeSystem = coding.getSystem();
       for (org.hl7.fhir.r4.model.Organization payor : payors) {
         String payorName = payor.getName();
+        String payorId = payor.getId();
         CoverageRequirementRuleCriteria criteria = new CoverageRequirementRuleCriteria();
-        criteria.setPayor(payorName).setCodeSystem(codeSystem).setCode(code).setFhirVersion("R4");
+        criteria.setPayor(payorName).setPayorId(payorId).setCodeSystem(codeSystem).setCode(code).setFhirVersion("R4");
         criteriaList.add(criteria);
       }
     }
