diff --git a/README.md b/README.md
index 08fdcdbb1..287bb55b2 100644
--- a/README.md
+++ b/README.md
@@ -112,3 +112,4 @@ Questions about the project can be asked in the [Da Vinci CRD stream on the FHIR
 
 This project welcomes Pull Requests. Any issues identified with the RI should be submitted via the [GitHub issue tracker](https://github.com/HL7-DaVinci/CRD/issues).
 
+ 
diff --git a/resources/src/main/java/org/cdshooks/CdsRequest.java b/resources/src/main/java/org/cdshooks/CdsRequest.java
index e6654b0e3..06a708b8d 100755
--- a/resources/src/main/java/org/cdshooks/CdsRequest.java
+++ b/resources/src/main/java/org/cdshooks/CdsRequest.java
@@ -1,7 +1,5 @@
 package org.cdshooks;
 
-import com.fasterxml.jackson.annotation.JsonGetter;
-
 import javax.validation.constraints.NotNull;
 import org.hl7.davinci.EncounterBasedServiceContext;
 
@@ -83,5 +81,18 @@ public void setContext(serviceContextTypeT context) {
    */
   public abstract Object getDataForPrefetchToken();
 
+  @Override
+  public String toString(){
+    StringBuilder sb = new StringBuilder();
+    sb.append("[hook: " + hook + "]");
+    sb.append("[hookInstance: " + hookInstance + "]");
+    sb.append("[fhirServer: " + fhirServer + "]");
+    sb.append("[fhirAuthorization: " + fhirAuthorization + "]");
+    sb.append("[context: " + context + "]");
+    sb.append("[extension: " + extension + "]");
+    sb.append("[prefetch: " + prefetch + "]");
+    return sb.toString();
+  }
+
 
 }
diff --git a/resources/src/main/java/org/cdshooks/Coding.java b/resources/src/main/java/org/cdshooks/Coding.java
new file mode 100644
index 000000000..ced8d63ad
--- /dev/null
+++ b/resources/src/main/java/org/cdshooks/Coding.java
@@ -0,0 +1,19 @@
+package org.cdshooks;
+
+public class Coding {
+
+    private String code;
+
+    private String system = null;
+
+    private String display = null;
+
+    public String getCode() { return code; }
+    public void setCode(String code) { this.code = code; }
+
+    public String getSystem() { return system; }
+    public void setSystem(String system) { this.system = system; }
+
+    public String getDisplay() { return display; }
+    public void setDisplay(String display) { this.display = display; }
+}
diff --git a/resources/src/main/java/org/cdshooks/Extension.java b/resources/src/main/java/org/cdshooks/Extension.java
index 3e9c17db8..672900eb8 100644
--- a/resources/src/main/java/org/cdshooks/Extension.java
+++ b/resources/src/main/java/org/cdshooks/Extension.java
@@ -10,4 +10,8 @@ public class Extension {
   public Configuration getConfiguration() { return configuration; }
 
   public void setConfiguration(Configuration configuration) { this.configuration = configuration; }
+
+  public String toString(){
+    return "Extension configuration: " + configuration;
+  }
 }
diff --git a/resources/src/main/java/org/cdshooks/Source.java b/resources/src/main/java/org/cdshooks/Source.java
index 05b138906..22b63acd6 100755
--- a/resources/src/main/java/org/cdshooks/Source.java
+++ b/resources/src/main/java/org/cdshooks/Source.java
@@ -5,13 +5,15 @@ public class Source {
 
   private String url = null;
 
+  private String icon = null;
+
+  private Coding topic = null;
+
   public String getLabel() {
     return label;
   }
 
-  public void setLabel(String label) {
-    this.label = label;
-  }
+  public void setLabel(String label) { this.label = label; }
 
   public String getUrl() {
     return url;
@@ -20,4 +22,12 @@ public String getUrl() {
   public void setUrl(String url) {
     this.url = url;
   }
+
+  public String getIcon() { return icon; }
+
+  public void setIcon(String icon) { this.icon = icon; }
+
+  public Coding getTopic() { return topic; }
+
+  public void setTopic(Coding topic) { this.topic = topic; }
 }
diff --git a/resources/src/main/java/org/hl7/davinci/EncounterBasedServiceContext.java b/resources/src/main/java/org/hl7/davinci/EncounterBasedServiceContext.java
index ddc1e1458..d217ce3dd 100644
--- a/resources/src/main/java/org/hl7/davinci/EncounterBasedServiceContext.java
+++ b/resources/src/main/java/org/hl7/davinci/EncounterBasedServiceContext.java
@@ -1,7 +1,10 @@
 package org.hl7.davinci;
 
+import org.hl7.fhir.r4.model.Bundle;
+
 public interface EncounterBasedServiceContext {
   String getUserId();
   String getPatientId();
   String getEncounterId();
+  Bundle getDraftOrders();
 }
diff --git a/resources/src/main/java/org/hl7/davinci/PrefetchTemplateElement.java b/resources/src/main/java/org/hl7/davinci/PrefetchTemplateElement.java
index 4f36920f3..d7cfbc6ad 100644
--- a/resources/src/main/java/org/hl7/davinci/PrefetchTemplateElement.java
+++ b/resources/src/main/java/org/hl7/davinci/PrefetchTemplateElement.java
@@ -30,4 +30,9 @@ public String getQuery() {
   public Class getReturnType() {
     return returnType;
   }
+
+  @Override
+  public String toString(){
+    return "[" + key + ", " + query + ", " + returnType + "]";
+  }
 }
\ No newline at end of file
diff --git a/resources/src/main/java/org/hl7/davinci/r4/CardTypes.java b/resources/src/main/java/org/hl7/davinci/r4/CardTypes.java
new file mode 100644
index 000000000..e1284a707
--- /dev/null
+++ b/resources/src/main/java/org/hl7/davinci/r4/CardTypes.java
@@ -0,0 +1,45 @@
+package org.hl7.davinci.r4;
+
+import org.cdshooks.Coding;
+
+public enum CardTypes {
+  COVERAGE("coverage", "Coverage"),
+  DOCUMENTATION("documentation", "Documentation"),
+  PRIOR_AUTH("prior-auth", "Prior Authorization"),
+  DTR_CLIN("dtr-clin", "DTR Clin"),
+  DTR_ADMIN("dtr-admin", "DTR Admin"),
+  CLAIM("claim", "Claim"),
+  INSURANCE("insurance", "Insurance"),
+  LIMITS("limits", "Limits"),
+  NETWORK("network", "Network"),
+  APPROPRIATE_USE("appropriate-use", "Appropriate Use"),
+  COST("cost", "Cost"),
+  THERAPY_ALTERNATIVES_OPT("therapy-alternatives-opt", "Therapy Alternatives Opt"),
+  THERAPY_ALTERNATIVES_REG("therapy-alternatives-req", "Therapy Alternatives Req"),
+  CLINICAL_REMINDER("clinical-reminder", "Clinical Reminder"),
+  DUPLICATE_THERAPY("duplicate-therapy", "Duplicate Therapy"),
+  CONTRAINDICATION("contraindication", "Contraindication"),
+  GUIDELINE("guideline", "Guideline"),
+  OFF_GUIDELINE("off-guideline", "Off Guideline");
+
+  private String code;
+  private String display;
+  private static String codeSystem = "http://hl7.org/fhir/us/davinci-crd/CodeSystem/cardType";
+
+  CardTypes(String code, String display) {
+    this.code = code;
+    this.display = display;
+  }
+
+  public String getCode() { return code; }
+  public String getDisplay() { return display; }
+  public String getCodeSystem() { return codeSystem; }
+
+  public Coding getCoding() {
+    Coding coding = new Coding();
+    coding.setSystem(codeSystem);
+    coding.setCode(code);
+    coding.setDisplay(display);
+    return coding;
+  }
+}
diff --git a/resources/src/main/java/org/hl7/davinci/r4/CoverageGuidance.java b/resources/src/main/java/org/hl7/davinci/r4/CoverageGuidance.java
new file mode 100644
index 000000000..94b808fa7
--- /dev/null
+++ b/resources/src/main/java/org/hl7/davinci/r4/CoverageGuidance.java
@@ -0,0 +1,33 @@
+package org.hl7.davinci.r4;
+
+import org.hl7.fhir.r4.model.Coding;
+
+public enum CoverageGuidance {
+  NOT_COVERED("not-covered", "Not Covered"),
+  COVERED("covered", "Covered"),
+  PRIOR_AUTH("prior-auth", "Prior authorization"),
+  CLINICAL("clinical", "Clinical"),
+  ADMIN("admin", "Admin");
+
+
+  private String code;
+  private String display;
+  private static String codeSystem = "http://hl7.org/fhir/us/davinci-crd/CodeSystem/coverageGuidance";
+
+  CoverageGuidance(String code, String display) {
+    this.code = code;
+    this.display = display;
+  }
+
+  public String getCode() { return code; }
+  public String getDisplay() { return display; }
+  public String getCodeSystem() { return codeSystem; }
+
+  public Coding getCoding() {
+    Coding coding = new Coding();
+    coding.setSystem(codeSystem);
+    coding.setCode(code);
+    coding.setDisplay(display);
+    return coding;
+  }
+}
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 e1821bc71..222269bff 100644
--- a/resources/src/main/java/org/hl7/davinci/r4/Utilities.java
+++ b/resources/src/main/java/org/hl7/davinci/r4/Utilities.java
@@ -4,6 +4,7 @@
 
 import ca.uhn.fhir.context.FhirContext;
 import ca.uhn.fhir.parser.IParser;
+
 import org.hl7.davinci.*;
 import org.hl7.fhir.instance.model.api.IBaseResource;
 import org.hl7.fhir.r4.model.*;
@@ -169,9 +170,13 @@ public static PractitionerRoleInfo getPractitionerRoleInfo(
   public static List<Organization> getPayors(List<Coverage> coverages) {
     List<Organization> payors = new ArrayList<>();
     for (Coverage coverage: coverages){
-      for (Reference ref: coverage.getPayor()){
-        Organization organization = (Organization) ref.getResource();
-        payors.add(organization);
+      if (coverage != null) {
+        for (Reference ref: coverage.getPayor()){
+          Organization organization = (Organization) ref.getResource();
+          if (organization != null) {
+            payors.add(organization);
+          }
+        }
       }
     }
     return payors;
diff --git a/resources/src/main/java/org/hl7/davinci/r4/crdhook/CrdPrefetch.java b/resources/src/main/java/org/hl7/davinci/r4/crdhook/CrdPrefetch.java
index 79623b6c8..528c1406c 100644
--- a/resources/src/main/java/org/hl7/davinci/r4/crdhook/CrdPrefetch.java
+++ b/resources/src/main/java/org/hl7/davinci/r4/crdhook/CrdPrefetch.java
@@ -1,10 +1,14 @@
 package org.hl7.davinci.r4.crdhook;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import org.hl7.davinci.r4.JacksonBundleDeserializer;
 import org.hl7.davinci.r4.JacksonHapiSerializer;
 import org.hl7.fhir.r4.model.*;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
 
 /**
  * Class that supports the representation of prefetch information in a CDS Hook request.
@@ -103,4 +107,74 @@ public void setSupplyRequestBundle(Bundle supplyRequestBundle) {
   public Bundle getMedicationStatementBundle() { return medicationStatementBundle; }
 
   public void setMedicationStatementBundle(Bundle medicationStatementBundle) { this.medicationStatementBundle = medicationStatementBundle; }
+
+  /**
+   * Checks whether the given resource exists in the requested resource type.
+   * @param id
+   * @return
+   */
+  public boolean containsRequestResourceId(String id) {
+    return this.bundleContainsResourceId(this.deviceRequestBundle, id)
+        || this.bundleContainsResourceId(this.medicationRequestBundle, id)
+        || this.bundleContainsResourceId(this.nutritionOrderBundle, id)
+        || this.bundleContainsResourceId(this.serviceRequestBundle, id)
+        || this.bundleContainsResourceId(this.supplyRequestBundle, id)
+        || this.bundleContainsResourceId(this.appointmentBundle, id)
+        || this.bundleContainsResourceId(this.encounterBundle, id)
+        || this.bundleContainsResourceId(this.medicationDispenseBundle, id)
+        || this.bundleContainsResourceId(this.medicationStatementBundle, id);
+  }
+
+  /**
+   * Returns whether the given bundle contains the given resource.
+   * @param bundle
+   * @param id
+   * @return
+   */
+  private boolean bundleContainsResourceId(Bundle bundle, String id) {
+    if (bundle == null) {
+      return false;
+    }
+    if (id.contains("/")) {
+      String[] splitId = id.split("/");
+      id = splitId[splitId.length-1];
+    }
+    final String idToCheck = id;
+    return bundle.getEntry().stream().anyMatch(entry -> entry.getResource().getId().contains(idToCheck));
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    List<BundleEntryComponent> entries = new ArrayList<>();
+    if(this.deviceRequestBundle != null){
+      entries = this.deviceRequestBundle.getEntry();
+    } else if(this.nutritionOrderBundle != null){
+      entries = this.nutritionOrderBundle.getEntry();
+    } else if(this.serviceRequestBundle != null){
+      entries = this.serviceRequestBundle.getEntry();
+    } else if(this.medicationDispenseBundle != null){
+      entries = this.medicationDispenseBundle.getEntry();
+    } else if(this.medicationStatementBundle != null){
+      entries = this.medicationStatementBundle.getEntry();
+    } else if(this.encounterBundle != null){
+      entries = this.encounterBundle.getEntry();
+    } else if(this.appointmentBundle != null){
+      entries = this.appointmentBundle.getEntry();
+    } else if(this.medicationRequestBundle != null){
+      entries = this.medicationRequestBundle.getEntry();
+    } else if(this.supplyRequestBundle != null){
+      entries = this.supplyRequestBundle.getEntry();
+    }
+    sb.append("[");
+    for(BundleEntryComponent entry : entries) {
+      sb.append(entry.getResource());
+      sb.append("-");
+      sb.append(entry.getResource().getId());
+      sb.append(",");
+    }
+    sb.setLength(sb.length()-1);
+    sb.append("]");
+    return sb.toString();
+  }
 }
diff --git a/resources/src/main/java/org/hl7/davinci/r4/crdhook/ordersign/OrderSignRequest.java b/resources/src/main/java/org/hl7/davinci/r4/crdhook/ordersign/OrderSignRequest.java
index 61a82c0d8..8ff435f65 100644
--- a/resources/src/main/java/org/hl7/davinci/r4/crdhook/ordersign/OrderSignRequest.java
+++ b/resources/src/main/java/org/hl7/davinci/r4/crdhook/ordersign/OrderSignRequest.java
@@ -32,5 +32,10 @@ public Object getDataForPrefetchToken() {
     return mapForPrefetchTemplates;
   }
 
+  @Override
+  public String toString() {
+    return "Super: " + super.toString() + " OrderSignRequest: " + getDataForPrefetchToken().toString();
+  }
+
 
 }
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 66c8de4f6..aa7b8abed 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,28 @@
 package org.hl7.davinci.endpoint.cdshooks.services.crd;
 
 
+import com.google.gson.Gson;
+
+import com.google.gson.Gson;
+
 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.components.CardBuilder;
-import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard;
 import org.hl7.davinci.endpoint.components.PrefetchHydrator;
+import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard;
+import org.hl7.davinci.endpoint.components.QueryBatchRequest;
 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.CoverageRequirementRuleResult;
+import org.hl7.davinci.r4.CardTypes;
+import org.hl7.davinci.r4.CoverageGuidance;
+import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest;
+import org.hl7.davinci.r4.crdhook.CrdPrefetch;
 import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
 import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest;
 import org.hl7.davinci.endpoint.database.FhirResourceRepository;
@@ -39,17 +48,17 @@ public abstract class CdsService<requestTypeT extends CdsRequest<?, ?>> extends
 
   @Autowired
   FileStore fileStore;
-  
+
   @Autowired
   private FhirResourceRepository fhirResourceRepository;
-  
+
   protected FhirComponentsT fhirComponents;
 
 
   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);
     this.fhirComponents = fhirComponents;
   }
@@ -74,18 +83,29 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
     // hydrated
     requestLog.advanceTimeline(requestService);
 
-    // logger.info("***** ***** request from requestLog: "+requestLog.toString() );
+    // Attempt a Query Batch Request to backfill missing attributes.
+    if (myConfig.isQueryBatchRequest()) {
+      QueryBatchRequest qbr = new QueryBatchRequest(this.fhirComponents);
+      this.attempQueryBatchRequest(request, qbr);
+    }
+
+    logger.info("***** ***** request from requestLog: " + requestLog.toString() );
 
     CdsResponse response = new CdsResponse();
 
+    Gson gson = new Gson();
+    final String jsonObject = gson.toJson(request.getPrefetch());
+    logger.info("Final populated CRDPrefetch: " + jsonObject);
+
     // CQL Fetched
     List<CoverageRequirementRuleResult> lookupResults;
     try {
       lookupResults = this.createCqlExecutionContexts(request, fileStore, applicationBaseUrl.toString() + "/");
       requestLog.advanceTimeline(requestService);
     } catch (RequestIncompleteException e) {
+      logger.warn("RequestIncompleteException " + request);
       logger.warn(e.getMessage() + "; summary card sent to client");
-      response.addCard(CardBuilder.summaryCard(e.getMessage()));
+      response.addCard(CardBuilder.summaryCard(CardTypes.COVERAGE, e.getMessage()));
       requestLog.setCardListFromCards(response.getCards());
       requestLog.setResults(e.getMessage());
       requestService.edit(requestLog);
@@ -133,7 +153,20 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireDispenseUri())
                 || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireAdditionalUri())) {
               List<Link> smartAppLinks = createQuestionnaireLinks(request, applicationBaseUrl, lookupResult, results);
-              response.addCard(CardBuilder.transform(results, smartAppLinks));
+
+              if (coverageRequirements.isPriorAuthRequired()) {
+                Card card = CardBuilder.transform(CardTypes.PRIOR_AUTH, results, smartAppLinks);
+                card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents,
+                    "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note",
+                    true, CoverageGuidance.ADMIN));
+                response.addCard(card);
+              } else if (coverageRequirements.isDocumentationRequired()) {
+                Card card = CardBuilder.transform(CardTypes.DTR_CLIN, results, smartAppLinks);
+                card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents,
+                    "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note",
+                    true, CoverageGuidance.CLINICAL));
+                response.addCard(card);
+              }
 
               // add a card for an alternative therapy if there is one
               if (results.getAlternativeTherapy().getApplies() && hookConfiguration.getAlternativeTherapy()) {
@@ -146,15 +179,15 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
               }
             } else {
               logger.warn("Unspecified Questionnaire URI; summary card sent to client");
-              response.addCard(CardBuilder.transform(results));
+              response.addCard(CardBuilder.transform(CardTypes.COVERAGE, results));
             }
           } else {
             // no prior auth or documentation required
             logger.info("Add the no doc or prior auth required card");
-            Card card = CardBuilder.transform(results);
+            Card card = CardBuilder.transform(CardTypes.COVERAGE, results);
             card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents,
                 "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note",
-                true));
+                true, CoverageGuidance.COVERED));
             card.setSelectionBehavior(Card.SelectionBehaviorEnum.ANY);
             response.addCard(card);
           }
@@ -174,9 +207,9 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
       if (!foundApplicableRule) {
         String msg = "No documentation rules found";
         logger.warn(msg + "; summary card sent to client");
-        response.addCard(CardBuilder.summaryCard(msg));
+        response.addCard(CardBuilder.summaryCard(CardTypes.COVERAGE, msg));
       }
-      CardBuilder.errorCardIfNonePresent(response);
+      CardBuilder.errorCardIfNonePresent(CardTypes.COVERAGE, response);
     }
 
     // Adding card to requestLog
@@ -257,4 +290,10 @@ public abstract List<CoverageRequirementRuleResult> createCqlExecutionContexts(r
       FileStore fileStore, String baseUrl) throws RequestIncompleteException;
 
   protected abstract CqlResultsForCard executeCqlAndGetRelevantResults(Context context, String topic);
+
+  /**
+   * Delegates query batch request to child classes based on their prefetch types.
+   */
+  protected abstract void attempQueryBatchRequest(requestTypeT request, QueryBatchRequest qbr);
+
 }
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
index 738373737..51055319e 100644
--- 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
@@ -7,6 +7,7 @@
 import org.hl7.davinci.FhirComponentsT;
 import org.hl7.davinci.PrefetchTemplateElement;
 import org.hl7.davinci.endpoint.components.CardBuilder;
+import org.hl7.davinci.r4.CardTypes;
 import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
 import org.hl7.fhir.r4.model.Coding;
 import org.slf4j.Logger;
@@ -61,7 +62,7 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a
         CdsResponse response = new CdsResponse();
         List<Coding> medications = getMedications(request);
         for (Coding medication : medications) {
-            Card card = CardBuilder.summaryCard("");
+            Card card = CardBuilder.summaryCard(CardTypes.COVERAGE, "");
             if (isRemsDrug(medication)) {
                 card.setSummary(String.format("%s has REMS", medication.getDisplay()));
             } else {
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..ffd498f6c 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
@@ -8,7 +8,6 @@
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria;
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult;
 import org.hl7.davinci.r4.Utilities;
-import org.hl7.davinci.r4.crdhook.CrdPrefetch;
 import org.hl7.fhir.r4.model.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -24,30 +23,27 @@ public class FhirBundleProcessor {
   static final Logger logger = LoggerFactory.getLogger(FhirBundleProcessor.class);
 
   private FileStore fileStore;
-  private CrdPrefetch prefetch;
   private String baseUrl;
   private List<String> selections;
   private List<CoverageRequirementRuleResult> results = new ArrayList<>();
 
 
-  public FhirBundleProcessor(CrdPrefetch prefetch, FileStore fileStore, String baseUrl, List<String> selections) {
-    this.prefetch = prefetch;
+  public FhirBundleProcessor(FileStore fileStore, String baseUrl, List<String> selections) {
     this.fileStore = fileStore;
     this.baseUrl = baseUrl;
     this.selections = selections;
   }
 
-  public FhirBundleProcessor(CrdPrefetch prefetch, FileStore fileStore, String baseUrl) {
-    this(prefetch, fileStore, baseUrl, new ArrayList<>());
+  public FhirBundleProcessor(FileStore fileStore, String baseUrl) {
+    this(fileStore, baseUrl, new ArrayList<>());
   }
 
   public List<CoverageRequirementRuleResult> getResults() { return results; }
 
-  public void processDeviceRequests() {
-    Bundle deviceRequestBundle = prefetch.getDeviceRequestBundle();
+  public void processDeviceRequests(Bundle deviceRequestBundle) {
     List<DeviceRequest> deviceRequestList = Utilities.getResourcesOfTypeFromBundle(DeviceRequest.class, deviceRequestBundle);
     if (!deviceRequestList.isEmpty()) {
-      logger.info("r4/FhirBundleProcessor::getAndProcessDeviceRequests: DeviceRequest(s) found");
+      logger.info("r4/FhirBundleProcessor::processDeviceRequests: DeviceRequest(s) found");
 
       for (DeviceRequest deviceRequest : deviceRequestList) {
         if (idInSelectionsList(deviceRequest.getId(), selections)) {
@@ -58,11 +54,10 @@ public void processDeviceRequests() {
     }
   }
 
-  public void processMedicationRequests() {
-    Bundle medicationRequestBundle = prefetch.getMedicationRequestBundle();
+  public void processMedicationRequests(Bundle medicationRequestBundle) {
     List<MedicationRequest> medicationRequestList = Utilities.getResourcesOfTypeFromBundle(MedicationRequest.class, medicationRequestBundle);
     if (!medicationRequestList.isEmpty()) {
-      logger.info("r4/FhirBundleProcessor::getAndProcessMedicationRequests: MedicationRequest(s) found");
+      logger.info("r4/FhirBundleProcessor::processMedicationRequests: MedicationRequest(s) found");
 
       for (MedicationRequest medicationRequest : medicationRequestList) {
         if (idInSelectionsList(medicationRequest.getId(), selections)) {
@@ -73,11 +68,10 @@ public void processMedicationRequests() {
     }
   }
 
-  public void processMedicationDispenses() {
-    Bundle medicationDispenseBundle = prefetch.getMedicationDispenseBundle();
+  public void processMedicationDispenses(Bundle medicationDispenseBundle) {
     List<MedicationDispense> medicationDispenseList = Utilities.getResourcesOfTypeFromBundle(MedicationDispense.class, medicationDispenseBundle);
     if (!medicationDispenseList.isEmpty()) {
-      logger.info("r4/FhirBundleProcessor::getAndProcessMedicationDispenses: MedicationDispense(s) found");
+      logger.info("r4/FhirBundleProcessor::processMedicationDispenses: MedicationDispense(s) found");
 
       List<Organization> payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class,
           medicationDispenseBundle);
@@ -91,11 +85,10 @@ public void processMedicationDispenses() {
     }
   }
 
-  public void processServiceRequests() {
-    Bundle serviceRequestBundle = prefetch.getServiceRequestBundle();
+  public void processServiceRequests(Bundle serviceRequestBundle) {
     List<ServiceRequest> serviceRequestList = Utilities.getResourcesOfTypeFromBundle(ServiceRequest.class, serviceRequestBundle);
     if (!serviceRequestList.isEmpty()) {
-      logger.info("r4/FhirBundleProcessor::getAndProcessServiceRequests: ServiceRequest(s) found");
+      logger.info("r4/FhirBundleProcessor::processServiceRequests: ServiceRequest(s) found");
 
       for (ServiceRequest serviceRequest : serviceRequestList) {
         if (idInSelectionsList(serviceRequest.getId(), selections)) {
@@ -106,11 +99,8 @@ public void processServiceRequests() {
     }
   }
 
-  public void processOrderSelectMedicationStatements() {
-    Bundle medicationRequestBundle = prefetch.getMedicationRequestBundle();
+  public void processOrderSelectMedicationStatements(Bundle medicationRequestBundle, Bundle medicationStatementBundle) {
     List<MedicationRequest> medicationRequestList = Utilities.getResourcesOfTypeFromBundle(MedicationRequest.class, medicationRequestBundle);
-
-    Bundle medicationStatementBundle = prefetch.getMedicationStatementBundle();
     List<MedicationStatement> medicationStatementList = Utilities.getResourcesOfTypeFromBundle(MedicationStatement.class, medicationStatementBundle);
 
     if (!medicationRequestList.isEmpty()) {
@@ -151,6 +141,8 @@ private List<CoverageRequirementRuleCriteria> createCriteriaList(CodeableConcept
       if (insurance != null) {
         List<Coverage> coverages = insurance.stream()
             .map(reference -> (Coverage) reference.getResource()).collect(Collectors.toList());
+        // Remove null coverages that may not have resolved.
+        coverages = coverages.stream().filter(coverage -> coverage != null).collect(Collectors.toList());
         payors = Utilities.getPayors(coverages);
       } else if (payorList != null) {
         payors = payorList;
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 912b97d8d..b65c61f3c 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,20 +1,36 @@
 package org.hl7.davinci.endpoint.cdshooks.services.crd.r4;
 
 import org.cdshooks.AlternativeTherapy;
-import org.hl7.fhir.instance.model.api.IBase;
+import org.cdshooks.CdsRequest;
+import org.hl7.davinci.FatalRequestIncompleteException;
+import org.hl7.davinci.FhirComponentsT;
+import org.hl7.davinci.r4.crdhook.CrdPrefetch;
 import org.hl7.fhir.instance.model.api.IBaseResource;
 import org.hl7.fhir.r4.model.*;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
+import com.google.gson.JsonElement;
+
 public class FhirRequestProcessor {
 
   static final Logger logger = LoggerFactory.getLogger(FhirRequestProcessor.class);
 
+  private static final String REFERENCE = "reference";
+
   public static IBaseResource swapTherapyInRequest(IBaseResource request, AlternativeTherapy alternativeTherapy) {
     IBaseResource output = request;
 
@@ -164,4 +180,334 @@ public static IBaseResource addSupportingInfoToRequest(IBaseResource request, Re
 
     return output;
   }
+
+  /**
+   * Adds the given resource to the given CrdPrefetch based on the given resource
+   * type.
+   * 
+   * @param crdResponse
+   * @param resource
+   * @param requestType
+   */
+  public static void addToCrdPrefetchRequest(CrdPrefetch crdResponse, ResourceType requestType,
+      List<BundleEntryComponent> resourcesToAdd) {
+    switch (requestType) {
+      case DeviceRequest:
+        if (crdResponse.getDeviceRequestBundle() == null) {
+          crdResponse.setDeviceRequestBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getDeviceRequestBundle(), resourcesToAdd);
+        break;
+      case MedicationRequest:
+        if (crdResponse.getMedicationRequestBundle() == null) {
+          crdResponse.setMedicationRequestBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getMedicationRequestBundle(), resourcesToAdd);
+        break;
+      case NutritionOrder:
+        if (crdResponse.getNutritionOrderBundle() == null) {
+          crdResponse.setNutritionOrderBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getNutritionOrderBundle(), resourcesToAdd);
+        break;
+      case ServiceRequest:
+        if (crdResponse.getServiceRequestBundle() == null) {
+          crdResponse.setServiceRequestBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getServiceRequestBundle(), resourcesToAdd);
+        break;
+      case SupplyRequest:
+        if (crdResponse.getSupplyRequestBundle() == null) {
+          crdResponse.setSupplyRequestBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getSupplyRequestBundle(), resourcesToAdd);
+        break;
+      case Appointment:
+        if (crdResponse.getAppointmentBundle() == null) {
+          crdResponse.setAppointmentBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getAppointmentBundle(), resourcesToAdd);
+        break;
+      case Encounter:
+        if (crdResponse.getEncounterBundle() == null) {
+          crdResponse.setEncounterBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getEncounterBundle(), resourcesToAdd);
+        break;
+      case MedicationDispense:
+        if (crdResponse.getMedicationDispenseBundle() == null) {
+          crdResponse.setMedicationDispenseBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getMedicationDispenseBundle(), resourcesToAdd);
+        break;
+      case MedicationStatement:
+        if (crdResponse.getMedicationStatementBundle() == null) {
+          crdResponse.setMedicationStatementBundle(new Bundle());
+        }
+        addNonDuplicateResourcesToBundle(crdResponse.getMedicationStatementBundle(), resourcesToAdd);
+        break;
+      default:
+        throw new RuntimeException("Unexpected resource type for draft order request. Given " + requestType + ".");
+    }
+  }
+
+  /**
+   * Adds non-duplicate resources that do not already exist in the bundle to the bundle.
+   */
+  private static void addNonDuplicateResourcesToBundle(Bundle bundle, List<BundleEntryComponent> resourcesToAdd) {
+    for (BundleEntryComponent resourceEntry : resourcesToAdd) {
+      if (!bundle.getEntry().stream()
+          .anyMatch(bundleEntry -> bundleEntry.getResource().getId().equals(resourceEntry.getResource().getId()))) {
+        bundle.addEntry(resourceEntry);
+      }
+    }
+  }
+
+  /**
+   * Extracts patients from the given bundle.
+   * @param bundle
+   * @return
+   */
+  public static List<Patient> extractPatientsFromBundle(Bundle bundle) {
+    List<Patient> patients = new ArrayList<>();
+    for (BundleEntryComponent entry : bundle.getEntry()) {
+      if (entry.getResource().getResourceType().equals(ResourceType.Patient)) {
+        patients.add((Patient) entry.getResource());
+      }
+    }
+    return patients;
+  }
+
+  /**
+   * Extracts the coverage elements from the given bundle.
+   * @param bundle
+   * @return
+   */
+  public static List<Coverage> extractCoverageFromBundle(Bundle bundle) {
+    List<Coverage> coverages = new ArrayList<>();
+    for (BundleEntryComponent entry : bundle.getEntry()) {
+      if (entry.getResource().getResourceType().equals(ResourceType.Coverage)) {
+        coverages.add((Coverage) entry.getResource());
+      }
+    }
+    return coverages;
+  }
+
+  /**
+   * Extracts the reference Ids from the given JSON.
+   * 
+   * @param references
+   * @param jsonElement
+   */
+  public static void extractReferenceIds(List<String> references, JsonElement jsonElement) {
+    if (jsonElement.isJsonArray()) {
+      for (JsonElement innerElement : jsonElement.getAsJsonArray()) {
+        extractReferenceIds(references, innerElement);
+      }
+    } else if (jsonElement.isJsonObject()) {
+      if (jsonElement.getAsJsonObject().has(REFERENCE)) {
+        if (jsonElement.getAsJsonObject().get(REFERENCE).isJsonObject()) {
+          String referenceId = jsonElement.getAsJsonObject().get(REFERENCE).getAsJsonObject()
+              .get("myStringValue").toString();
+          references.add(referenceId.replace("\"", ""));
+        }
+      }
+    }
+  }
+
+  /**
+   * Adds the given coverage and patient to the given resource.
+   * @param resource  The resource to add coverage and patient data to.
+   * @param patients  The list of valid patients.
+   * @param coverages The list of valid coverages.
+   */
+  public static void addInsuranceAndSubject(Resource resource, List<Patient> patients, List<Coverage> coverages) {
+    // Source: https://build.fhir.org/ig/HL7/davinci-crd/hooks.html#prefetch
+    switch(resource.getResourceType()){
+      case DeviceRequest:
+        DeviceRequest deviceRequest = (DeviceRequest) resource;
+        if(!coverages.isEmpty()){
+          deviceRequest.getInsuranceFirstRep().setResource(coverages.get(0));
+        }
+        if(!patients.isEmpty()){
+          deviceRequest.getSubject().setResource(patients.get(0));
+        }
+        break;
+      case Encounter:
+        Encounter encounter = (Encounter) resource;
+        // Encounter does not have an insurance field.
+        if(!patients.isEmpty()){
+          encounter.getSubject().setResource(patients.get(0));
+        }
+        break;
+      case MedicationRequest:
+        MedicationRequest medicationRequest = (MedicationRequest) resource;
+        if(!coverages.isEmpty()){
+          medicationRequest.getInsuranceFirstRep().setResource(coverages.get(0));
+        }
+        if(!patients.isEmpty()){
+          medicationRequest.getSubject().setResource(patients.get(0));
+        }
+      case MedicationDispense:
+        MedicationDispense dispense = (MedicationDispense) resource;
+        // MedicationDispense does not have an insurance field.
+        // It is also not defined in the prefetch section of the spec, though that is likely a typo from the duplicated MedicationRequest.
+        if(!patients.isEmpty()){
+          dispense.getSubject().setResource(patients.get(0));
+        }
+        break;
+      case ServiceRequest:
+        ServiceRequest serviceRequest = (ServiceRequest) resource;
+        if(!coverages.isEmpty()){
+          serviceRequest.getInsuranceFirstRep().setResource(coverages.get(0));
+        }
+        if(!patients.isEmpty()){
+          serviceRequest.getSubject().setResource(patients.get(0));
+        }
+        break;
+      case NutritionOrder:
+        // NutritionOrder does not define an insurance or subject field.
+      case Appointment:
+        // Appointment does not define an insurance or subject field.
+      default:
+        // The input request type is not one of the 7 defined above and in the spec.
+        throw new RuntimeException("Invalid request type: " + resource.getResourceType() + ".");
+    }
+  }
+
+  /**
+   * Execute a Fhir Query with a URL-based query.
+   * @param queryUrl
+   * @param cdsRequest
+   * @param fhirComponents
+   * @param httpMethod
+   * @return
+   */
+  public static IBaseResource executeFhirQueryUrl(String queryUrl, CdsRequest<?, ?> cdsRequest,
+      FhirComponentsT fhirComponents, HttpMethod httpMethod) {
+    return executeFhirQuery("", queryUrl, cdsRequest, fhirComponents, httpMethod);
+  }
+
+  /**
+   * Execute a Fhir Query with a body-based query.
+   * @param queryBody
+   * @param cdsRequest
+   * @param fhirComponents
+   * @param httpMethod
+   * @return
+   */
+  public static IBaseResource executeFhirQueryBody(String queryBody, CdsRequest<?, ?> cdsRequest,
+      FhirComponentsT fhirComponents, HttpMethod httpMethod) {
+    return executeFhirQuery(queryBody, "", cdsRequest, fhirComponents, httpMethod);
+  }
+
+  /**
+   * Execute a Fhir query with the given query body and query url.
+   * @param queryBody
+   * @param queryUrl
+   * @param cdsRequest
+   * @param fhirComponents
+   * @param httpMethod
+   * @return
+   */
+  public static IBaseResource executeFhirQuery(String queryBody, String queryUrl, CdsRequest<?, ?> cdsRequest,
+      FhirComponentsT fhirComponents, HttpMethod httpMethod) {
+    if (cdsRequest.getFhirServer() == null) {
+      throw new FatalRequestIncompleteException("Attempted to perform a Query Batch Request, but no fhir "
+          + "server provided.");
+    }
+    // Remove the trailing '/' if there is one.
+    String fhirBase = cdsRequest.getFhirServer();
+    if (fhirBase != null && fhirBase.endsWith("/")) {
+      fhirBase = fhirBase.substring(0, fhirBase.length() - 1);
+    }
+    String fullUrl = fhirBase + "/" + queryUrl;
+    //    TODO: Once our provider fhir server is up, switch the fetch to use the hapi client instead
+    //    cdsRequest.getOauth();
+    //    FhirContext ctx = FhirContext.forR4();
+    //    BearerTokenAuthInterceptor authInterceptor = new BearerTokenAuthInterceptor(oauth.get("access_token"));
+    //    IGenericClient client = ctx.newRestfulGenericClient(server);
+    //    client.registerInterceptor(authInterceptor);
+    //    return client;
+    //    IGenericClient client = ctx.newRestfulGenericClient(serverBase);
+    //    return client.search().byUrl(query).encodedJson().returnBundle(Bundle.class).execute();
+
+    String token = null;
+    if (cdsRequest.getFhirAuthorization() != null) {
+      token = cdsRequest.getFhirAuthorization().getAccessToken();
+    }
+
+    RestTemplate restTemplate = new RestTemplate();
+    HttpHeaders headers = new HttpHeaders();
+    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+    if(!queryBody.isEmpty()){
+      headers.setContentType(MediaType.APPLICATION_JSON);
+    }
+    if (token != null) {
+      headers.set("Authorization", "Bearer " + token);
+    }
+    HttpEntity<String> entity = new HttpEntity<>(queryBody, headers);
+    try {
+      logger.info("Fetching: " + fullUrl);
+      // Request source: https://www.hl7.org/fhir/http.html#transaction
+      ResponseEntity<String> response = restTemplate.exchange(fullUrl, httpMethod, entity, String.class);
+      logger.info("Fetched: " + response.getBody());
+      return fhirComponents.getJsonParser().parseResource(response.getBody());
+    } catch (RestClientException e) {
+      logger.warn("Unable to make the fetch request", e);
+      return null;
+    }
+  }
+ 
+  public static IBaseResource addExtensionToRequest(IBaseResource request, Extension extension) {
+    IBaseResource output = request;
+
+    switch (request.fhirType()) {
+      case "DeviceRequest":
+      case "MedicationRequest":
+      case "CommunicationRequest":
+      case "ServiceRequest":
+      case "NutritionOrder":
+      case "Appointment":
+      case "Encounter":
+        DomainResource domainResource = ((DomainResource) request);
+        domainResource.addExtension(extension);
+        output = domainResource;
+        break;
+      default:
+        logger.info("Unsupported fhir R4 resource type (" + request.fhirType() + ") when adding extension");
+        throw new RuntimeException("Unsupported fhir R4 resource type " + request.fhirType());
+    }
+
+    return output;
+  }
+
+  public static Reference getCoverageFromRequest(IBaseResource request) {
+    Reference coverage = null;
+
+    switch (request.fhirType()) {
+      case "DeviceRequest":
+        DeviceRequest deviceRequest = ((DeviceRequest) request).copy();
+        coverage = deviceRequest.getInsurance().get(0);
+        break;
+      case "MedicationRequest":
+        MedicationRequest medicationRequest = ((MedicationRequest) request).copy();
+        coverage = medicationRequest.getInsurance().get(0);
+        break;
+      case "ServiceRequest":
+        ServiceRequest serviceRequest = ((ServiceRequest) request).copy();
+        coverage = serviceRequest.getInsurance().get(0);
+        break;
+      case "MedicationDispense":
+      case "Appointment":
+      case "NutritionOrder":
+      case "SupplyRequest":
+      case "Encounter":
+      default:
+        logger.info("Unsupported fhir R4 resource type (" + request.fhirType() + ") when retrieving coverage");
+        throw new NoCoverageException("No coverage found within fhir R4 resource type " + request.fhirType());
+    }
+
+    return coverage;
+  }
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/NoCoverageException.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/NoCoverageException.java
new file mode 100644
index 000000000..3ec68ddd7
--- /dev/null
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/NoCoverageException.java
@@ -0,0 +1,13 @@
+package org.hl7.davinci.endpoint.cdshooks.services.crd.r4;
+
+
+public class NoCoverageException extends RuntimeException {
+  
+    public NoCoverageException() { super(); }
+  
+    public NoCoverageException(String message) { super(message); }
+  
+    public NoCoverageException(String message, Throwable cause) { super(message, cause); }
+  
+    public NoCoverageException(Throwable cause) { super(cause); }
+  }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectService.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectService.java
index 503a57e64..83b6a00ec 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectService.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectService.java
@@ -13,9 +13,11 @@
 import org.hl7.davinci.RequestIncompleteException;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsService;
 import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard;
+import org.hl7.davinci.endpoint.components.QueryBatchRequest;
 import org.hl7.davinci.endpoint.files.FileStore;
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult;
 import org.hl7.davinci.r4.FhirComponents;
+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.Coding;
@@ -46,8 +48,9 @@ public List<CoverageRequirementRuleResult> createCqlExecutionContexts(OrderSelec
 
     List<String> selections = Arrays.asList(orderSelectRequest.getContext().getSelections());
 
-    FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(orderSelectRequest.getPrefetch(), fileStore, baseUrl, selections);
-    fhirBundleProcessor.processOrderSelectMedicationStatements();
+    FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(fileStore, baseUrl, selections);
+    CrdPrefetch prefetch = orderSelectRequest.getPrefetch();
+    fhirBundleProcessor.processOrderSelectMedicationStatements(prefetch.getMedicationRequestBundle(), prefetch.getMedicationStatementBundle());
     List<CoverageRequirementRuleResult> results = fhirBundleProcessor.getResults();
 
     if (results.isEmpty()) {
@@ -113,4 +116,9 @@ private Coding getFirstCodeFromCodingListObject(Object c) {
     }
     return codingList.get(0);
   }
+
+  @Override
+  protected void attempQueryBatchRequest(OrderSelectRequest request, QueryBatchRequest batchRequest) {
+    batchRequest.performQueryBatchRequest(request, request.getPrefetch());
+  }
 }
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 8b9c7d2ba..778f2c736 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
@@ -12,11 +12,13 @@
 import org.hl7.davinci.PrefetchTemplateElement;
 import org.hl7.davinci.RequestIncompleteException;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsService;
+import org.hl7.davinci.endpoint.components.QueryBatchRequest;
 import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard;
 import org.hl7.davinci.endpoint.files.FileStore;
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult;
 import org.hl7.davinci.r4.FhirComponents;
 import org.hl7.davinci.r4.crdhook.ConfigurationOption;
+import org.hl7.davinci.r4.crdhook.CrdPrefetch;
 import org.hl7.davinci.r4.crdhook.DiscoveryExtension;
 import org.hl7.davinci.r4.crdhook.ordersign.CrdExtensionConfigurationOptions;
 import org.hl7.davinci.r4.crdhook.ordersign.CrdPrefetchTemplateElements;
@@ -57,11 +59,12 @@ public class OrderSignService extends CdsService<OrderSignRequest> {
 
   @Override
   public List<CoverageRequirementRuleResult> createCqlExecutionContexts(OrderSignRequest orderSignRequest, FileStore fileStore, String baseUrl) {
-    FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(orderSignRequest.getPrefetch(), fileStore, baseUrl);
-    fhirBundleProcessor.processDeviceRequests();
-    fhirBundleProcessor.processMedicationRequests();
-    fhirBundleProcessor.processServiceRequests();
-    fhirBundleProcessor.processMedicationDispenses();
+    FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(fileStore, baseUrl);
+    CrdPrefetch prefetch = orderSignRequest.getPrefetch();
+    fhirBundleProcessor.processDeviceRequests(prefetch.getDeviceRequestBundle());
+    fhirBundleProcessor.processMedicationRequests(prefetch.getMedicationRequestBundle());
+    fhirBundleProcessor.processServiceRequests(prefetch.getServiceRequestBundle());
+    fhirBundleProcessor.processMedicationDispenses(prefetch.getMedicationDispenseBundle());
     List<CoverageRequirementRuleResult> results = fhirBundleProcessor.getResults();
 
     if (results.isEmpty()) {
@@ -221,4 +224,9 @@ protected CqlResultsForCard executeCqlAndGetRelevantResults(Context context, Str
 
     return results;
   }
+
+  @Override
+  protected void attempQueryBatchRequest(OrderSignRequest orderSignRequest, QueryBatchRequest batchRequest) {
+    batchRequest.performQueryBatchRequest(orderSignRequest, orderSignRequest.getPrefetch());
+  }
 }
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 e67ff6f42..be77f9232 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
@@ -5,12 +5,15 @@
 import org.cdshooks.*;
 import org.hl7.davinci.FhirComponentsT;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.FhirRequestProcessor;
+import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.NoCoverageException;
 import org.hl7.davinci.endpoint.database.FhirResource;
 import org.hl7.davinci.endpoint.database.FhirResourceRepository;
+import org.hl7.davinci.r4.CardTypes;
+import org.hl7.davinci.r4.CoverageGuidance;
 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.*;
+import org.hl7.fhir.r4.model.Extension;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -77,11 +80,12 @@ public CqlResultsForCard setRequest(IBaseResource request) {
   /**
    * Transforms a result from the database into a card.
    *
+   * @param cardType
    * @param cqlResults
    * @return card with appropriate information
    */
-  public static Card transform(CqlResultsForCard cqlResults, Boolean addLink) {
-    Card card = baseCard();
+  public static Card transform(CardTypes cardType, CqlResultsForCard cqlResults, Boolean addLink) {
+    Card card = baseCard(cardType);
 
     if (addLink) {
       Link link = new Link();
@@ -100,22 +104,24 @@ public static Card transform(CqlResultsForCard cqlResults, Boolean addLink) {
   /**
    * Transforms a result from the database into a card, defaults to adding the link.
    *
+   * @param cardType
    * @param cqlResults
    * @return card with appropriate information
    */
-  public static Card transform(CqlResultsForCard cqlResults) {
-    return transform(cqlResults, true);
+  public static Card transform(CardTypes cardType, CqlResultsForCard cqlResults) {
+    return transform(cardType, cqlResults, true);
   }
 
   /**
    * Transforms a result from the database into a card.
    *
+   * @param cardType
    * @param cqlResults
    * @param smartAppLaunchLink smart app launch Link
    * @return card with appropriate information
    */
-  public static Card transform(CqlResultsForCard cqlResults, Link smartAppLaunchLink) {
-    Card card = transform(cqlResults);
+  public static Card transform(CardTypes cardType, CqlResultsForCard cqlResults, Link smartAppLaunchLink) {
+    Card card = transform(cardType, cqlResults);
     List<Link> links = new ArrayList<Link>(card.getLinks());
     links.add(smartAppLaunchLink);
     card.setLinks(links);
@@ -125,12 +131,13 @@ public static Card transform(CqlResultsForCard cqlResults, Link smartAppLaunchLi
   /**
    * Tranform the CQL results for card
    * then add a list of smart app launch links to the card
+   * @param cardType
    * @param cqlResults The CQL results
    * @param smartAppLaunchLinks a list of links
    * @return card to be returned
    */
-  public static Card transform(CqlResultsForCard cqlResults, List<Link> smartAppLaunchLinks) {
-    Card card = transform(cqlResults);
+  public static Card transform(CardTypes cardType, CqlResultsForCard cqlResults, List<Link> smartAppLaunchLinks) {
+    Card card = transform(cardType, cqlResults);
     List<Link> links = new ArrayList<Link>(card.getLinks());
     links.addAll(smartAppLaunchLinks);
     card.setLinks(links);
@@ -140,11 +147,12 @@ public static Card transform(CqlResultsForCard cqlResults, List<Link> smartAppLa
   /**
    * Creates a card with a summary but also has all of the necessary fields populated to be valid.
    *
+   * @param cardType
    * @param summary The desired summary for the card
    * @return valid card
    */
-  public static Card summaryCard(String summary) {
-    Card card = baseCard();
+  public static Card summaryCard(CardTypes cardType, String summary) {
+    Card card = baseCard(cardType);
     card.setSummary(summary);
     return card;
   }
@@ -152,7 +160,7 @@ public static Card summaryCard(String summary) {
   public static Card alternativeTherapyCard(AlternativeTherapy alternativeTherapy, IBaseResource resource,
                                             FhirComponentsT fhirComponents) {
     logger.info("Build Alternative Therapy Card: " + alternativeTherapy.toString());
-    Card card = baseCard();
+    Card card = baseCard(CardTypes.THERAPY_ALTERNATIVES_OPT);
 
     card.setSummary("Alternative Therapy Suggested");
     card.setDetail(alternativeTherapy.getDisplay() + " (" + alternativeTherapy.getCode() + ") should be used instead.");
@@ -197,7 +205,7 @@ public static Card alternativeTherapyCard(AlternativeTherapy alternativeTherapy,
 
   public static Card drugInteractionCard(DrugInteraction drugInteraction) {
     logger.info("Build Drug Interaction Card: " + drugInteraction.getSummary());
-    Card card = baseCard();
+    Card card = baseCard(CardTypes.CONTRAINDICATION);
     card.setSummary(drugInteraction.getSummary());
     card.setDetail(drugInteraction.getDetail());
     card.setIndicator(Card.IndicatorEnum.WARNING);
@@ -215,7 +223,7 @@ public static Card priorAuthCard(CqlResultsForCard cqlResults,
                                    FhirResourceRepository fhirResourceRepository) {
     logger.info("Build Prior Auth Card");
 
-    Card card = transform(cqlResults, false);
+    Card card = transform(CardTypes.PRIOR_AUTH, cqlResults, false);
 
     // create the ClaimResponse
     ClaimResponse claimResponse = Utilities.createClaimResponse(priorAuthId, patientId, payerId, providerId, applicationFhirPath);
@@ -239,13 +247,13 @@ public static Card priorAuthCard(CqlResultsForCard cqlResults,
 
     // add suggestion with ClaimResponse
     Suggestion suggestionWithClaimResponse = createSuggestionWithResource(outputRequest, claimResponse, fhirComponents,
-        "Store the prior authorization in the EHR");
+        "Store the prior authorization in the EHR", true);
     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);
+        false, CoverageGuidance.PRIOR_AUTH);
     card.addSuggestionsItem(suggestionWithAnnotation);
 
     card.setSelectionBehavior(Card.SelectionBehaviorEnum.AT_MOST_ONE);
@@ -256,11 +264,12 @@ public static Card priorAuthCard(CqlResultsForCard cqlResults,
   public static Suggestion createSuggestionWithResource(IBaseResource request,
                                                         IBaseResource resource,
                                                         FhirComponentsT fhirComponents,
-                                                        String label) {
+                                                        String label,
+                                                        boolean isRecommended) {
     Suggestion suggestion = new Suggestion();
 
     suggestion.setLabel(label);
-    suggestion.setIsRecommended(true);
+    suggestion.setIsRecommended(isRecommended);
 
     // build the create Action
     Action createAction = new Action(fhirComponents);
@@ -278,12 +287,15 @@ public static Suggestion createSuggestionWithResource(IBaseResource request,
 
     return suggestion;
   }
+
   public static Suggestion createSuggestionWithNote(Card card,
                                                     IBaseResource request,
                                                     FhirComponentsT fhirComponents,
                                                     String label,
                                                     String description,
-                                                    boolean isRecommended) {
+                                                    boolean isRecommended,
+                                                    CoverageGuidance coverageGuidance) {
+    Date now = new Date();
     Suggestion requestWithNoteSuggestion = new Suggestion();
 
     requestWithNoteSuggestion.setLabel(label);
@@ -297,9 +309,77 @@ public static Suggestion createSuggestionWithNote(Card card,
     annotation.setAuthor(author);
     String text = card.getSummary() + ": " + card.getDetail();
     annotation.setText(text);
-    annotation.setTime(new Date()); // set the date and time to now
+    annotation.setTime(now); // set the date and time to now
     IBaseResource resource = FhirRequestProcessor.addNoteToRequest(request, annotation);
 
+    try {
+      // build the Extension with the coverage information
+      Extension extension = new Extension();
+      extension.setUrl("http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information");
+
+      Extension coverageInfo = new Extension();
+      coverageInfo.setUrl("coverageInfo")
+          .setValue(coverageGuidance.getCoding());
+      extension.addExtension(coverageInfo);
+
+      Extension coverageExtension = new Extension();
+      Reference coverageReference = new Reference();
+
+      //TODO: get the coverage from the prefetch and pass it into here instead of retrieving it from the request
+      coverageReference.setReference(FhirRequestProcessor.getCoverageFromRequest(request).getReference());
+
+      coverageExtension.setUrl("coverage")
+          .setValue(coverageReference);
+      extension.addExtension(coverageExtension);
+
+      Extension date = new Extension();
+      date.setUrl("date")
+          .setValue(new DateType().setValue(now));
+      extension.addExtension(date);
+      Extension identifier = new Extension();
+      String id = UUID.randomUUID().toString();
+      identifier.setUrl("identifier")
+          .setValue(new StringType(id));
+      extension.addExtension(identifier);
+      resource = FhirRequestProcessor.addExtensionToRequest(resource, extension);
+    } catch (NoCoverageException e) {
+      logger.warn("No Coverage, discrete coverage extension will not be included: " + e.getMessage());
+    }
+
+    try {
+      // build the Extension with the coverage information
+      Extension extension = new Extension();
+      extension.setUrl("http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information");
+
+      Extension coverageInfo = new Extension();
+      coverageInfo.setUrl("coverageInfo")
+          .setValue(coverageGuidance.getCoding());
+      extension.addExtension(coverageInfo);
+
+      Extension coverageExtension = new Extension();
+      Reference coverageReference = new Reference();
+
+      //TODO: get the coverage from the prefetch and pass it into here instead of retrieving it from the request
+      coverageReference.setReference(FhirRequestProcessor.getCoverageFromRequest(request).getReference());
+
+      coverageExtension.setUrl("coverage")
+          .setValue(coverageReference);
+      extension.addExtension(coverageExtension);
+
+      Extension date = new Extension();
+      date.setUrl("date")
+          .setValue(new DateType().setValue(now));
+      extension.addExtension(date);
+      Extension identifier = new Extension();
+      String id = UUID.randomUUID().toString();
+      identifier.setUrl("identifier")
+          .setValue(new StringType(id));
+      extension.addExtension(identifier);
+      resource = FhirRequestProcessor.addExtensionToRequest(resource, extension);
+    } catch (NoCoverageException e) {
+      logger.warn("No Coverage, discrete coverage extension will not be included: " + e.getMessage());
+    }
+
     Action updateAction = new Action(fhirComponents);
     updateAction.setType(Action.TypeEnum.update);
     updateAction.setDescription(description);
@@ -311,19 +391,25 @@ public static Suggestion createSuggestionWithNote(Card card,
     return requestWithNoteSuggestion;
   }
 
+  private static Source createSource(CardTypes cardType) {
+    Source source = new Source();
+    source.setLabel("Da Vinci CRD Reference Implementation");
+    source.setTopic(cardType.getCoding());
+    return source;
+  }
+
   /**
    * Creates an error card and adds it to the response if the response that is passed in does not
    * contain any cards.
    *
+   * @param cardType
    * @param response The response to check and add cards to
    */
-  public static void errorCardIfNonePresent(CdsResponse response) {
+  public static void errorCardIfNonePresent(CardTypes cardType, CdsResponse response) {
     if (response.getCards() == null || response.getCards().size() == 0) {
       Card card = new Card();
       card.setIndicator(Card.IndicatorEnum.WARNING);
-      Source source = new Source();
-      source.setLabel("Da Vinci CRD Reference Implementation");
-      card.setSource(source);
+      card.setSource(createSource(cardType));
       String msg = "Unable to process hook request from provided information.";
       card.setSummary(msg);
       response.addCard(card);
@@ -331,12 +417,10 @@ public static void errorCardIfNonePresent(CdsResponse response) {
     }
   }
 
-  private static Card baseCard() {
+  private static Card baseCard(CardTypes cardType) {
     Card card = new Card();
     card.setIndicator(Card.IndicatorEnum.INFO);
-    Source source = new Source();
-    source.setLabel("Da Vinci CRD Reference Implementation");
-    card.setSource(source);
+    card.setSource(createSource(cardType));
     return card;
   }
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/components/PrefetchHydrator.java b/server/src/main/java/org/hl7/davinci/endpoint/components/PrefetchHydrator.java
index d72538e9a..8f5c109f0 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/components/PrefetchHydrator.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/components/PrefetchHydrator.java
@@ -2,7 +2,6 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.regex.Pattern;
 import org.apache.commons.beanutils.PropertyUtils;
@@ -12,16 +11,11 @@
 import org.hl7.davinci.FhirComponentsT;
 import org.hl7.davinci.PrefetchTemplateElement;
 import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsService;
+import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.FhirRequestProcessor;
 import org.hl7.fhir.instance.model.api.IBaseResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.client.RestClientException;
-import org.springframework.web.client.RestTemplate;
 
 public class PrefetchHydrator {
 
@@ -116,10 +110,6 @@ public void hydrate() {
         // check if the bundle actually has element
         String prefetchQuery = cdsService.prefetch.get(prefetchKey);
         String hydratedPrefetchQuery = hydratePrefetchQuery(prefetchQuery);
-        String token = null;
-        if (cdsRequest.getFhirAuthorization() != null) {
-          token = cdsRequest.getFhirAuthorization().getAccessToken();
-        }
         // if we can't hydrate the query, it probably means we didnt get an apprpriate resource
         // e.g. this could be a query template for a medication order but we have a device request
         if (hydratedPrefetchQuery != null) {
@@ -130,8 +120,8 @@ public void hydrate() {
           try {
             PropertyUtils
                 .setProperty(crdResponse, prefetchKey,
-                    prefetchElement.getReturnType().cast(
-                        executeFhirQuery(hydratedPrefetchQuery, token)));
+                    prefetchElement.getReturnType().cast(FhirRequestProcessor.executeFhirQueryUrl(
+                      hydratedPrefetchQuery, cdsRequest, fhirComponents, HttpMethod.GET)));
           } catch (Exception e) {
             logger.warn("Failed to fill prefetch for key: " + prefetchKey, e);
           }
@@ -140,36 +130,6 @@ public void hydrate() {
     }
   }
 
-  private IBaseResource executeFhirQuery(String query, String token) {
-    String fullUrl = cdsRequest.getFhirServer() + query;
-    //    TODO: Once our provider fhir server is up, switch the fetch to use the hapi client instead
-    //    cdsRequest.getOauth();
-    //    FhirContext ctx = FhirContext.forR4();
-    //    BearerTokenAuthInterceptor authInterceptor = new BearerTokenAuthInterceptor(oauth.get("access_token"));
-    //    IGenericClient client = ctx.newRestfulGenericClient(server);
-    //    client.registerInterceptor(authInterceptor);
-    //    return client;
-    //    IGenericClient client = ctx.newRestfulGenericClient(serverBase);
-    //    return client.search().byUrl(query).encodedJson().returnBundle(Bundle.class).execute();
-
-    RestTemplate restTemplate = new RestTemplate();
-    HttpHeaders headers = new HttpHeaders();
-    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
-    if (token != null) {
-      headers.set("Authorization", "Bearer " + token);
-    }
-    HttpEntity<String> entity = new HttpEntity<>("", headers);
-    try {
-      logger.debug("Fetching: " + fullUrl);
-      ResponseEntity<String> response = restTemplate.exchange(fullUrl, HttpMethod.GET,
-          entity, String.class);
-      return fhirComponents.getJsonParser().parseResource(response.getBody());
-    } catch (RestClientException e) {
-      logger.warn("Unable to make the fetch request", e);
-      return null;
-    }
-  }
-
   private String hydratePrefetchQuery(String prefetchQuery) {
     String[] tokenList = StringUtils.substringsBetween(
         prefetchQuery, PREFETCH_TOKEN_DELIM_OPEN, PREFETCH_TOKEN_DELIM_CLOSE);
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/components/QueryBatchRequest.java b/server/src/main/java/org/hl7/davinci/endpoint/components/QueryBatchRequest.java
new file mode 100644
index 000000000..b3c1b7467
--- /dev/null
+++ b/server/src/main/java/org/hl7/davinci/endpoint/components/QueryBatchRequest.java
@@ -0,0 +1,181 @@
+package org.hl7.davinci.endpoint.components;
+
+import org.cdshooks.CdsRequest;
+import org.hl7.davinci.FhirComponentsT;
+import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.FhirRequestProcessor;
+import org.hl7.davinci.r4.crdhook.CrdPrefetch;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryRequestComponent;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Coverage;
+import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.Resource;
+import org.hl7.fhir.r4.model.ResourceType;
+import org.hl7.fhir.r4.model.Bundle.BundleType;
+import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpMethod;
+
+import ca.uhn.fhir.context.FhirContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+/**
+ * A Query Batch Request can be used to populate fields in a CDS Request that a Prefetch may have missed.
+ */
+public class QueryBatchRequest {
+
+  private static final Logger logger = LoggerFactory.getLogger(QueryBatchRequest.class);
+  private static final String PRACTIONER_ROLE = "PractitionerRole";
+
+  private final FhirComponentsT fhirComponents;
+
+  public QueryBatchRequest(FhirComponentsT fhirComponents) {
+    this.fhirComponents = fhirComponents;
+  }
+
+  /**
+   * Backfills the missing required values of the response that prefetch may have missed.
+   * This implementation pulls the IDs of the required references from the request object's draft
+   * orders, checks which of those values are missing from the current CRD response, builds the
+   * Query Batch JSON request using
+   * http://build.fhir.org/ig/HL7/davinci-crd/hooks.html#fhir-resource-access,
+   * then populates the CRD response with the response from the Query Batch.
+   */
+  public void performQueryBatchRequest(CdsRequest<?, ?> cdsRequest, CrdPrefetch crdPrefetch) {
+    logger.info("***** ***** Performing Query Batch Request.");
+    CrdPrefetch crdResponse = crdPrefetch;
+    // The list of references that should be queried in the batch request.
+    List<String> requiredReferences = new ArrayList<String>();
+
+    // Get the IDs of references in the request's draft orders.
+    Bundle draftOrdersBundle = cdsRequest.getContext().getDraftOrders();
+    // This assumes that only the first draft order is relevant.
+    Resource initialRequestResource = draftOrdersBundle.getEntry().get(0).getResource();
+    ResourceType requestType = initialRequestResource.getResourceType();
+    // Extract the references by iterating through the JSON.
+    Gson gson = new Gson();
+    final JsonObject jsonObject = gson.toJsonTree(initialRequestResource).getAsJsonObject();
+    for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+      FhirRequestProcessor.extractReferenceIds(requiredReferences, entry.getValue());
+    }
+
+    // Filter out references that already exist in the CRD Response.
+    requiredReferences = requiredReferences.stream()
+        .filter(referenceId -> !crdResponse.containsRequestResourceId(referenceId))
+        .collect(Collectors.toList());
+
+    logger.info("References to query: " + requiredReferences);
+    if (requiredReferences.isEmpty()) {
+      logger.info("A Query Batch Request is not needed: all references have already already fetched.");
+      return;
+    }
+
+    // Build the Query Batch Request JSON.
+    Bundle queryBatchRequestBundle = buildQueryBatchRequestBundle(requiredReferences);
+    String queryBatchRequestBody = FhirContext.forR4().newJsonParser().encodeResourceToString(queryBatchRequestBundle);
+
+    // Make the query batch request to the EHR server.
+    Bundle queryResponseBundle = null;
+    try {
+      logger.info("Executing Query Batch Request: " + queryBatchRequestBody);
+      queryResponseBundle = (Bundle) FhirRequestProcessor.executeFhirQueryBody(queryBatchRequestBody, cdsRequest, this.fhirComponents, HttpMethod.POST);
+      queryResponseBundle = extractNestedBundledResources(queryResponseBundle);
+      logger.info("Extracted Query Batch Resources: "
+          + (queryResponseBundle).getEntry().stream().map(entry -> entry.getResource()).collect(Collectors.toList()));
+    } catch (Exception e) {
+      logger.error("Failed to backfill prefetch with Query Batch Request " + queryBatchRequestBody, e);
+    }
+
+    if (queryResponseBundle == null) {
+      logger.error("No response recieved from the Query Batch Request.");
+      return;
+    }
+
+    // Add the request resource to the query batch response as it may be missing.
+    // Coverage and Subject are not automatically being
+    // linked to the request object. It seems to somehow automatically link during
+    // standard prefetch, but not here so we're doing it manually.
+    List<Coverage> coverages = FhirRequestProcessor.extractCoverageFromBundle(queryResponseBundle);
+    List<Patient> patients = FhirRequestProcessor.extractPatientsFromBundle(queryResponseBundle);
+    FhirRequestProcessor.addInsuranceAndSubject(initialRequestResource, patients, coverages);
+    BundleEntryComponent newEntry = new BundleEntryComponent();
+    newEntry.setResource(initialRequestResource);
+    queryResponseBundle.addEntry(newEntry);
+
+    // Add the query batch response resources to the CRD Prefetch request.
+    logger.info("Query Batch Response Entries: " + queryResponseBundle.getEntry());
+    FhirRequestProcessor.addToCrdPrefetchRequest(crdResponse, requestType, queryResponseBundle.getEntry());
+    logger.info("Post-Query Batch CRDResponse: " + crdResponse);
+  }
+
+  /**
+   * Builds a query batch request bundle based on the given references to request.
+   * 
+   * @param resourceReferences
+   * @return
+   */
+  private static Bundle buildQueryBatchRequestBundle(List<String> resourceReferences) {
+    // http://build.fhir.org/ig/HL7/davinci-crd/hooks.html#fhir-resource-access
+    Bundle queryBatchBundle = new Bundle();
+    queryBatchBundle.setType(BundleType.BATCH);
+    for (String reference : resourceReferences) {
+      if (reference.contains(PRACTIONER_ROLE)) {
+        reference = QueryBatchRequest.buildPractionerRoleQuery(reference);
+      }
+      BundleEntryComponent entry = new BundleEntryComponent();
+      BundleEntryRequestComponent request = new BundleEntryRequestComponent();
+      request.setMethod(HTTPVerb.GET);
+      request.setUrl(reference);
+      entry.setRequest(request);
+      queryBatchBundle.addEntry(entry);
+    }
+    return queryBatchBundle;
+  }
+
+  /**
+   * Adds support for PractitionerRole nested requests.
+   * 
+   * @param reference
+   * @return
+   */
+  private static String buildPractionerRoleQuery(String reference) {
+    String[] referenceIdSplit = reference.split("/");
+    String referenceId = referenceIdSplit[referenceIdSplit.length - 1];
+    String query = "PractitionerRole?_id=" + referenceId
+        + "&_include=PractitionerRole:organization&_include=PractitionerRole:practitioner&_include=PractitionerRole:location";
+    return query;
+  }
+
+  /**
+   * Extracts the resources inside a bundled bundle to be at the top level of the
+   * bundle, making them no longer nested.
+   * 
+   * @param resource
+   * @return
+   */
+  private static Bundle extractNestedBundledResources(Bundle bundle) {
+    List<BundleEntryComponent> entriesToAdd = new ArrayList<>();
+    List<BundleEntryComponent> entriesToRemove = new ArrayList<>();
+    for (int bundleIndex = 0; bundleIndex < bundle.getEntry().size(); bundleIndex++) {
+      BundleEntryComponent entry = bundle.getEntry().get(bundleIndex);
+      if (entry.getResource().getResourceType().equals(ResourceType.Bundle)) {
+        Bundle bundledBundle = (Bundle) entry.getResource();
+        entriesToAdd.addAll(bundledBundle.getEntry());
+        entriesToRemove.add(entry);
+      }
+    }
+    bundle.getEntry().addAll(entriesToAdd);
+    bundle.getEntry().removeAll(entriesToRemove);
+    return bundle;
+  }
+
+}
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/config/YamlConfig.java b/server/src/main/java/org/hl7/davinci/endpoint/config/YamlConfig.java
index 7116d6122..c31a67e4a 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/config/YamlConfig.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/config/YamlConfig.java
@@ -39,6 +39,8 @@ public class YamlConfig {
 
   private boolean urlEncodeAppContext;
 
+  private boolean queryBatchRequest;
+
   public boolean getCheckJwt() {
     return checkJwt;
   }
@@ -57,10 +59,18 @@ public void setCheckPractitionerLocation(boolean checkPractitionerLocation) {
     this.checkPractitionerLocation = checkPractitionerLocation;
   }
 
+  public void setQueryBatchRequest(boolean queryBatchRequest) {
+    this.queryBatchRequest = queryBatchRequest;
+  }
+
   public boolean isCheckPractitionerLocation() {
     return checkPractitionerLocation;
   }
 
+  public boolean isQueryBatchRequest() {
+    return this.queryBatchRequest;
+  }
+
   public boolean isAppendParamsToSmartLaunchUrl() {
     return appendParamsToSmartLaunchUrl;
   }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/controllers/FhirController.java b/server/src/main/java/org/hl7/davinci/endpoint/controllers/FhirController.java
index 7b57cfdf1..dfb5925fb 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/controllers/FhirController.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/controllers/FhirController.java
@@ -5,6 +5,7 @@
 import org.hl7.davinci.endpoint.Utils;
 import org.hl7.davinci.endpoint.database.FhirResource;
 import org.hl7.davinci.endpoint.database.FhirResourceRepository;
+import org.hl7.davinci.endpoint.fhir.r4.QuestionnairePackageOperation;
 import org.hl7.davinci.endpoint.files.FileResource;
 import org.hl7.davinci.endpoint.files.FileStore;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -20,6 +21,7 @@
 import java.util.logging.Logger;
 import javax.servlet.http.HttpServletRequest;
 
+
 /**
  * Provides the REST interface that can be interacted with at [base]/api/fhir and [base]/fhir.
  */
@@ -116,9 +118,9 @@ public ResponseEntity<Resource> getFhirResourceById(HttpServletRequest request,
    * @return
    * @throws IOException
    */
-  @GetMapping(path = "/fhir/{fhirVersion}/{resource}") //?name={topic}
+  @GetMapping(path = "/fhir/{fhirVersion}/{resource}") //?name={TopicFormName}
   public ResponseEntity<Resource> searchFhirResource(HttpServletRequest request, @PathVariable String fhirVersion,
-                                                     @PathVariable String resource, @RequestParam(required = false) String name, @RequestParam(required = false) String url) throws IOException {
+                                                     @PathVariable String resource, @RequestParam(required = false) String name, @RequestParam(required = false) String url, @RequestParam(required = false) String topic) throws IOException {
 
     fhirVersion = fhirVersion.toUpperCase();
     resource = resource.toLowerCase();
@@ -129,12 +131,17 @@ public ResponseEntity<Resource> searchFhirResource(HttpServletRequest request, @
     if (name != null) {
       name = name.toLowerCase();
       logger.info("GET /fhir/" + fhirVersion + "/" + resource + "?name=" + name);
-      fileResource = fileStore.getFhirResourceByTopic(fhirVersion, resource, name, baseUrl);
+      fileResource = fileStore.getFhirResourceByName(fhirVersion, resource, name, baseUrl);
     }
     else if (url != null) {
       logger.info("GET /fhir/" + fhirVersion + "/" + resource + "?url=" + url);
       fileResource = fileStore.getFhirResourceByUrl(fhirVersion, resource, url, baseUrl);
     }
+    else if (topic != null) {
+      topic = topic.toLowerCase();
+      logger.info("GET /fhir/" + fhirVersion + "/" + resource + "?topic=" + topic);
+      fileResource = fileStore.getFhirResourcesByTopicAsBundle(fhirVersion, resource, topic, baseUrl);
+    }
 
     return processFileResource(fileResource);
   }
@@ -171,7 +178,6 @@ public ResponseEntity<String> submitFhirResource(HttpServletRequest request, Htt
       logger.warning("unsupported FHIR version: " + fhirVersion + ", not storing");
       HttpStatus status = HttpStatus.BAD_REQUEST;
       MediaType contentType = MediaType.TEXT_PLAIN;
-      String baseUrl = Utils.getApplicationBaseUrl(request).toString() + "/";
 
       return ResponseEntity.status(status).contentType(contentType)
           .body("Bad Request");
@@ -181,7 +187,6 @@ public ResponseEntity<String> submitFhirResource(HttpServletRequest request, Htt
       logger.warning("submitFhirResource: unsupported FHIR Resource of type: " + fhirResourceInfo.getType() + " (" + fhirVersion + "), not storing");
       HttpStatus status = HttpStatus.BAD_REQUEST;
       MediaType contentType = MediaType.TEXT_PLAIN;
-      String baseUrl = Utils.getApplicationBaseUrl(request).toString() + "/";
 
       return ResponseEntity.status(status).contentType(contentType)
           .body("Bad Request");
@@ -213,4 +218,46 @@ public ResponseEntity<String> submitFhirResource(HttpServletRequest request, Htt
         .header(HttpHeaders.LOCATION, baseUrl + "/fhir/" + fhirVersion + "/" + resource + "?identifier=" + newId)
         .body(statusMsg);
   }
+
+  /**
+   * FHIR Operation to retrieve all of the Questionnaires and CQL files associated with a given request.
+   * @param fhirVersion (converted to uppercase)
+   * @return FHIR Bundle
+   * @throws IOException
+   */
+  @PostMapping(path = "/fhir/{fhirVersion}/Questionnaire/$questionnaire-package", consumes = { MediaType.APPLICATION_JSON_VALUE, "application/fhir+json" })
+  public ResponseEntity<String> questionnaireForOrderOperation(HttpServletRequest request, HttpEntity<String> entity,
+                                                   @PathVariable String fhirVersion) {
+
+    fhirVersion = fhirVersion.toUpperCase();
+    String baseUrl = Utils.getApplicationBaseUrl(request).toString() + "/";
+
+    logger.info("POST /fhir/" + fhirVersion + "/Questionnaire/$Questionnaire-package");
+
+    String resource = null;
+    if (fhirVersion.equalsIgnoreCase("R4")) {
+      QuestionnairePackageOperation operation = new QuestionnairePackageOperation(fileStore, baseUrl);
+      resource = operation.execute(entity.getBody());
+
+      if (resource == null) {
+        logger.warning("bad parameters");
+        HttpStatus status = HttpStatus.BAD_REQUEST;
+        MediaType contentType = MediaType.TEXT_PLAIN;
+        
+        return ResponseEntity.status(status).contentType(contentType)
+            .body("Bad Parameters");
+      }
+
+    } else {
+      logger.warning("unsupported FHIR version: " + fhirVersion + ", not storing");
+      HttpStatus status = HttpStatus.BAD_REQUEST;
+      MediaType contentType = MediaType.TEXT_PLAIN;
+
+      return ResponseEntity.status(status).contentType(contentType)
+          .body("Bad Request");
+    }
+
+    return ResponseEntity.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
+          .body(resource);
+  }
 }
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 08f8e50af..b70442cef 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
@@ -7,6 +7,7 @@ public class FhirResourceCriteria {
   private String name = null;
   private String id = null;
   private String url = null;
+  private String topic = null;
 
   public String getFhirVersion() { return fhirVersion; }
 
@@ -43,6 +44,13 @@ public FhirResourceCriteria setUrl(String url) {
     return this;
   }
 
+  public String getTopic() { return topic; }
+
+  public FhirResourceCriteria setTopic(String topic) {
+    this.topic = topic;
+    return this;
+  }
+
   public String toString() {
     String string = new String();
     boolean first = true;
@@ -90,6 +98,15 @@ public String toString() {
       }
       string = string + "url=" + url;
     }
+
+    if (topic != null) {
+      if (first) {
+        first = false;
+      } else {
+        string = string + ", ";
+      }
+      string = string + "topic=" + topic;
+    }
     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 5d01a8a0f..88563ab61 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
@@ -27,7 +27,7 @@ List<FhirResource> findById(
       "SELECT r FROM FhirResource r WHERE "
           + "r.fhirVersion = :#{#criteria.fhirVersion} "
           + "and LOWER(r.resourceType) = :#{#criteria.resourceType} "
-          + "and r.name = :#{#criteria.name}")
+          + "and LOWER(r.name) = :#{#criteria.name}")
   List<FhirResource> findByName(
       @Param("criteria") FhirResourceCriteria criteria
   );
@@ -41,6 +41,15 @@ List<FhirResource> findByUrl(
       @Param("criteria") FhirResourceCriteria criteria
   );
 
+  @Query(
+      "SELECT r FROM FhirResource r WHERE "
+          + "r.fhirVersion = :#{#criteria.fhirVersion} "
+          + "and LOWER(r.resourceType) = :#{#criteria.resourceType} "
+          + "and LOWER(r.topic) = :#{#criteria.topic}")
+  List<FhirResource> findByTopic(
+      @Param("criteria") FhirResourceCriteria criteria
+  );
+
   @Query(
       "SELECT r FROM FhirResource r "
           + "order by r.topic, r.id")
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/Metadata.java b/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/Metadata.java
index c3186fe73..3043354f3 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/Metadata.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/Metadata.java
@@ -86,9 +86,14 @@ private CapabilityStatement buildCapabilityStatement(String baseUrl) {
     questionnaire.addInteraction().setCode(TypeRestfulInteraction.READ);
     questionnaire.addInteraction().setCode(TypeRestfulInteraction.SEARCHTYPE);
     questionnaire.addInteraction().setCode(TypeRestfulInteraction.CREATE);
+    CapabilityStatementRestResourceOperationComponent questionnairePackageOperation = new CapabilityStatementRestResourceOperationComponent();
+    questionnairePackageOperation.setName("questionnaire-package");
+    questionnairePackageOperation.setDefinition("http://hl7.org/fhir/us/davinci-dtr/OperationDefinition/Questionnaire-package");
+    questionnairePackageOperation.setDocumentation("Retrieve the Questionnaire(s), Libraries, and Valuesets for a given order and coverage. This operation is to support HL7 DaVinci DTR.");
+    questionnaire.addOperation(questionnairePackageOperation);
     rest.addResource(questionnaire);
 
-    // QuestionnaireResponse REsource
+    // QuestionnaireResponse Resource
     CapabilityStatementRestResourceComponent questionnaireResponse = new CapabilityStatementRestResourceComponent();
     questionnaireResponse.setType("QuestionnaireResponse");
     questionnaireResponse.addInteraction().setCode(TypeRestfulInteraction.READ);
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/QuestionnairePackageOperation.java b/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/QuestionnairePackageOperation.java
new file mode 100644
index 000000000..5f0e432e9
--- /dev/null
+++ b/server/src/main/java/org/hl7/davinci/endpoint/fhir/r4/QuestionnairePackageOperation.java
@@ -0,0 +1,250 @@
+package org.hl7.davinci.endpoint.fhir.r4;
+
+import org.hl7.davinci.endpoint.cdshooks.services.crd.r4.FhirBundleProcessor;
+import org.hl7.davinci.endpoint.files.FileStore;
+import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
+import org.hl7.fhir.r4.model.CanonicalType;
+import org.hl7.fhir.r4.model.Coverage;
+import org.hl7.fhir.r4.model.DataRequirement;
+import org.hl7.fhir.r4.model.Extension;
+import org.hl7.fhir.r4.model.Library;
+import org.hl7.fhir.r4.model.Parameters;
+import org.hl7.fhir.r4.model.Questionnaire;
+import org.hl7.fhir.r4.model.RelatedArtifact;
+import org.hl7.fhir.r4.model.Resource;
+import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent;
+import org.hl7.fhir.r4.model.RelatedArtifact.RelatedArtifactType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ca.uhn.fhir.parser.DataFormatException;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.parser.IParser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+//TODO: handle operation being passed one or more canonicals specifying the URL and, optionally, the version of the Questionnaire(s) to retrieve
+
+public class QuestionnairePackageOperation {
+    
+    static final Logger logger = LoggerFactory.getLogger(QuestionnairePackageOperation.class);
+
+    FileStore fileStore;
+    String baseUrl;
+
+    // map of Resources and ids/urls so that we can skip retrieving duplicates
+    HashMap<String, Resource> resources = new HashMap<>();
+
+    public QuestionnairePackageOperation(FileStore fileStore, String baseUrl) {
+        this.fileStore = fileStore;
+        this.baseUrl = baseUrl;
+    }
+
+    /*
+     * Do the work retrieving all of the Questionnaire, Library and Valueset Resources.
+     */
+    public String execute(String resourceString) {
+        Parameters outputParameters = new Parameters();    
+        IBaseResource resource = null;
+
+        try {
+            resource = org.hl7.davinci.r4.Utilities.parseFhirData(resourceString);
+        } catch (DataFormatException exception) {
+            logger.error("Failed to process input parameters: " + exception.getMessage());
+            return null;
+        }
+
+        if (resource.fhirType().equalsIgnoreCase("Parameters")) {
+            Parameters parameters = (Parameters)resource;
+
+            //TODO: handle multiple FHIR Coverage Resources
+            Coverage coverage = (Coverage) getResource(parameters, "coverage");
+
+            // list of all of the orders
+            Bundle orders = getAllResources(parameters, "order");
+
+            if (coverage == null || orders.isEmpty()) {
+                logger.error("Failed to find order or coverage within parameters");
+                return null;
+            }
+
+            // create a single new bundle for all of the resources
+            Bundle completeBundle = new Bundle();
+
+            // list of items in bundle to avoid duplicates
+            List<String> bundleContents = new ArrayList<>();
+
+            // process the orders to find the topics
+            FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(fileStore, baseUrl);
+            fhirBundleProcessor.processDeviceRequests(orders);
+            fhirBundleProcessor.processMedicationRequests(orders);
+            fhirBundleProcessor.processServiceRequests(orders);
+            fhirBundleProcessor.processMedicationDispenses(orders);
+            List<String> topics = createTopicList(fhirBundleProcessor);
+
+            for (String topic : topics) {
+                logger.info("--> process topic: " + topic);
+
+                // get all of the Quesionnaires for the topic
+                Bundle bundle = fileStore.getFhirResourcesByTopicAsFhirBundle("R4", "Questionnaire", topic.toLowerCase(), baseUrl);
+                List<BundleEntryComponent> bundleEntries = bundle.getEntry();
+                for (BundleEntryComponent entry : bundleEntries) {
+
+                    addResourceToBundle(entry.getResource(), bundleContents, completeBundle);
+
+                    if (entry.getResource().fhirType().equalsIgnoreCase("Questionnaire")) {
+                        Questionnaire questionnaire = (Questionnaire)entry.getResource();
+
+                        List<Extension> extensions = questionnaire.getExtension();
+                        for (Extension extension : extensions) {
+                            if (extension.getUrl().endsWith("cqf-library")) {
+                                CanonicalType data = (CanonicalType)extension.getValue();
+                                String url = data.asStringValue();
+                                Resource libraryResource = null;
+
+                                // look in the map and retrieve it instead of looking it up on disk if found
+                                if (resources.containsKey(url)) {
+                                    libraryResource = resources.get(url);
+                                } else {
+                                    libraryResource = fileStore.getFhirResourceByUrlAsFhirResource("R4", "Library", url, baseUrl);
+                                    resources.put(url, libraryResource);
+                                }
+
+                                if (addResourceToBundle(libraryResource, bundleContents, completeBundle)) {
+                                    // recursively add the depends-on libraries if added to bundle
+                                    addLibraryDependencies((Library)libraryResource, bundleContents, completeBundle);
+                                }
+                            }
+                        }
+                    }
+                } // Questionnaires
+            } // topics
+
+            // add the bundle to the output parameters if it contains any resources
+            if (!completeBundle.isEmpty()) {
+                ParametersParameterComponent parameter = new ParametersParameterComponent();
+                parameter.setName("return");
+                parameter.setResource(completeBundle);
+                outputParameters.addParameter(parameter);
+            } else {
+                logger.info("No matching Questionnaires found");
+            }
+        }
+
+        // if none found return null
+        if (outputParameters.isEmpty()) {
+            return null;
+        }
+
+        // convert the outputParameters to a string
+        FhirContext ctx = new org.hl7.davinci.r4.FhirComponents().getFhirContext();
+        IParser parser = ctx.newJsonParser().setPrettyPrint(true);
+        return parser.encodeResourceToString(outputParameters);
+    }
+
+    private Resource getResource(Parameters parameters, String name) {
+        for (ParametersParameterComponent parameter : parameters.getParameter()) {
+            if (parameter.getName().equals(name))
+                return parameter.getResource();
+        }
+        return null;
+    }
+
+    private Bundle getAllResources(Parameters parameters, String name) {
+        Bundle foundResources = new Bundle();
+        for (ParametersParameterComponent parameter : parameters.getParameter()) {
+            if (parameter.getName().equals(name))
+                foundResources.addEntry(new BundleEntryComponent().setResource(parameter.getResource()));
+            }
+
+        return foundResources;
+    }
+
+    private boolean addResourceToBundle(Resource resource, List<String> bundleContents, Bundle questionnaireBundle) {
+        // only add the library if not already in the bundle
+        boolean added = false;
+        if (!bundleContents.contains(resource.getId())) {
+            // add the questionnaire to the bundle
+            BundleEntryComponent questionnaireBundleEntry = new BundleEntryComponent();
+            questionnaireBundleEntry.setResource(resource);
+            questionnaireBundle.addEntry(questionnaireBundleEntry);
+            bundleContents.add(resource.getId());
+            logger.info("    --> add " + resource.fhirType() + ": " + resource.getId());
+            added = true;
+        }
+        return added;
+    }
+
+    private List<String> createTopicList(FhirBundleProcessor fhirBundleProcessor) {
+        List<String> topics = new ArrayList<>();
+        List<CoverageRequirementRuleResult> results = fhirBundleProcessor.getResults();
+        for (CoverageRequirementRuleResult result : results) {
+            // add topic to the list if not already contained
+            if (!topics.contains(result.getTopic())) {
+                topics.add(result.getTopic());
+            }
+        }
+        return topics;
+    }
+
+    /*
+    * Recursively add all of the libraries dependencies related by the "depends-on" type.
+    */
+    private void addLibraryDependencies(Library library, List<String> bundleContents, Bundle questionnaireBundle) {
+        List<RelatedArtifact> relatedArtifacts = library.getRelatedArtifact();
+        for (RelatedArtifact relatedArtifact : relatedArtifacts) {
+            // only add the depends-on artifacts
+            if (relatedArtifact.getType() == RelatedArtifactType.DEPENDSON) {
+                String relatedArtifactReferenceString = relatedArtifact.getResource();
+                String[] referenceParts = relatedArtifactReferenceString.split("/");
+                String id = referenceParts[1];
+                Resource referencedLibraryResource = null;
+
+                // look in the map and retrieve it instead of looking it up on disk if found
+                if (resources.containsKey(id)) {
+                    referencedLibraryResource = resources.get(id);
+                } else {
+                    referencedLibraryResource = fileStore.getFhirResourceByIdAsFhirResource("R4", "Library", id, baseUrl);
+                    resources.put(id, referencedLibraryResource);
+                }
+
+                // only add the library if not already in the bundle
+                if (!bundleContents.contains(referencedLibraryResource.getId())) {
+                    BundleEntryComponent referencedLibraryBundleEntry = new BundleEntryComponent();
+                    referencedLibraryBundleEntry.setResource(referencedLibraryResource);
+                    questionnaireBundle.addEntry(referencedLibraryBundleEntry);
+                    bundleContents.add(referencedLibraryResource.getId());
+
+                    // recurse through the libraries...
+                    addLibraryDependencies((Library)referencedLibraryResource, bundleContents, questionnaireBundle);
+                }
+            }
+        }
+
+        // grab all of the ValueSets in the DataRequirement
+        List<DataRequirement> dataRequirements = library.getDataRequirement();
+        for (DataRequirement dataRequirement : dataRequirements) {
+            List<DataRequirement.DataRequirementCodeFilterComponent> codeFilters = dataRequirement.getCodeFilter();
+            for (DataRequirement.DataRequirementCodeFilterComponent codeFilter : codeFilters) {
+                String valueSetUrl = codeFilter.getValueSet();
+                Resource valueSetResource = null;
+
+                // look in the map and retrieve it instead of looking it up on disk if found
+                if (resources.containsKey(valueSetUrl)) {
+                    valueSetResource = resources.get(valueSetUrl);
+                } else {
+                    valueSetResource = fileStore.getFhirResourceByUrlAsFhirResource("R4", "ValueSet", valueSetUrl, baseUrl);
+                    resources.put(valueSetUrl, valueSetResource);
+                }
+
+                addResourceToBundle(valueSetResource, bundleContents, questionnaireBundle);
+            }
+        }
+    }
+}
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 8615c8fc5..83aca77f9 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
@@ -12,17 +12,24 @@
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria;
 import org.hl7.davinci.endpoint.vsac.ValueSetCache;
 import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Resource;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.InputStreamResource;
 
 import java.io.*;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.util.List;
+import java.util.ArrayList;
 import java.util.Locale;
 
+import javax.annotation.processing.Filer;
+
 public abstract class CommonFileStore implements FileStore {
 
   static final Logger logger = LoggerFactory.getLogger(CommonFileStore.class);
@@ -67,47 +74,66 @@ public CommonFileStore() {
 
   protected abstract String readFhirResourceFromFile(FhirResource fhirResource, String fhirVersion);
 
-  protected FileResource readFhirResourceFromFiles(List<FhirResource> fhirResourceList, String fhirVersion,
+  protected FileResource readFhirResourceFromFiles(FhirResource fhirResource, String fhirVersion,
       String baseUrl) {
-    if (!fhirResourceList.isEmpty()) {
-      // just return the first matched resource
-      FhirResource fhirResource = fhirResourceList.get(0);
-      String fileString = null;
+    String fileString = null;
 
-      // grab the data from the database directly if it is there
-      String data = fhirResource.getData();
-      if (data != null) {
-        fileString = data;
-      } else {
-        fileString = readFhirResourceFromFile(fhirResource, fhirVersion);
-      }
+    // grab the data from the database directly if it is there
+    String data = fhirResource.getData();
+    if (data != null) {
+      fileString = data;
+    } else {
+      fileString = readFhirResourceFromFile(fhirResource, fhirVersion);
+    }
 
-      if (fileString != null) {
-        String partialUrl = baseUrl + "fhir/" + fhirVersion + "/";
+    if (fileString != null) {
+      String partialUrl = baseUrl + "fhir/" + fhirVersion + "/";
 
-        // replace <server-path> with the proper path
-        fileString = fileString.replace("<server-path>", partialUrl);
-        byte[] fileData = fileString.getBytes(Charset.defaultCharset());
+      // replace <server-path> with the proper path
+      fileString = fileString.replace("<server-path>", partialUrl);
+      byte[] fileData = fileString.getBytes(Charset.defaultCharset());
 
-        FileResource fileResource = new FileResource();
-        fileResource.setFilename(fhirResource.getFilename());
-        fileResource.setResource(new ByteArrayResource(fileData));
-        return fileResource;
-      } else {
-        logger.warn("CommonFhirStore::readFhirResourceFromFiles() empty fileString");
-        return null;
-      }
+      FileResource fileResource = new FileResource();
+      fileResource.setFilename(fhirResource.getFilename());
+      fileResource.setResource(new ByteArrayResource(fileData));
+      return fileResource;
+    } else {
+      logger.warn("CommonFhirStore::readFhirResourceFromFiles() empty fileString");
+      return null;
+    }
+  }
 
+  protected FileResource readFhirResourceFromFiles(List<FhirResource> fhirResourceList, String fhirVersion,
+      String baseUrl) {
+    if (!fhirResourceList.isEmpty()) {
+      // just return the first matched resource
+      FhirResource fhirResource = fhirResourceList.get(0);
+      return readFhirResourceFromFiles(fhirResource, fhirVersion, baseUrl);
     } else {
       logger.warn("CommonFileStore::readFhirResourceFromFiles() empty file resource list");
       return null;
     }
   }
 
-  public FileResource getFhirResourceByTopic(String fhirVersion, String resourceType, String name, String baseUrl) {
+  protected List<FileResource> readFhirResourcesFromFiles(List<FhirResource> fhirResourceList, String fhirVersion,
+      String baseUrl) {
+    List<FileResource> fileResources = new ArrayList<>();
+
+    // read all of the resources from the list from the file store
+    for (FhirResource fhirResource : fhirResourceList) {
+      FileResource fileResource = readFhirResourceFromFiles(fhirResource, fhirVersion, baseUrl);
+      if (fileResource != null) {
+        fileResources.add(fileResource);
+      }
+    }
+
+    return fileResources;
+  }
+
+  public FileResource getFhirResourceByName(String fhirVersion, String resourceType, String name, String baseUrl) {
     FhirResourceCriteria criteria = new FhirResourceCriteria();
     criteria.setFhirVersion(fhirVersion).setResourceType(resourceType.toLowerCase()).setName(name);
-    logger.info("CommonFileStore::getFhirResourceByTopic(): " + criteria.toString());
+    logger.info("CommonFileStore::getFhirResourceByName(): " + criteria.toString());
 
     List<FhirResource> fhirResourceList = fhirResources.findByName(criteria);
     FileResource resource = readFhirResourceFromFiles(fhirResourceList, fhirVersion, baseUrl);
@@ -181,6 +207,106 @@ public FileResource getFhirResourceByUrl(String fhirVersion, String resourceType
     return resource;
   }
 
+
+  private Resource convertFileResourceToFhirResource(FileResource fileResource) {
+    if (fileResource == null) {
+      return null;
+    } else {
+      Resource resource = null;
+      try {
+        // convert the file resource into the fhir resource
+        resource = (Resource) parser.parseResource(fileResource.getResource().getInputStream());
+      } catch(IOException ioe) {
+        logger.error("Issue parsing FHIR file resource when retrieving by URL.", ioe);
+      }
+      return resource;
+    }
+  }
+
+  public Resource getFhirResourceByIdAsFhirResource(String fhirVersion, String resourceType, String id, String baseUrl) {
+    FileResource fileResource = getFhirResourceById(fhirVersion, resourceType, id, baseUrl);
+    return convertFileResourceToFhirResource(fileResource);
+  }
+
+  public Resource getFhirResourceByUrlAsFhirResource(String fhirVersion, String resourceType, String url, String baseUrl) {
+    FileResource fileResource = getFhirResourceByUrl(fhirVersion, resourceType, url, baseUrl);
+    return convertFileResourceToFhirResource(fileResource);
+  }
+
+  public List<FileResource> getFhirResourcesByTopic(String fhirVersion, String resourceType, String topic, String baseUrl) {
+    FhirResourceCriteria criteria = new FhirResourceCriteria();
+    criteria.setFhirVersion(fhirVersion).setResourceType(resourceType.toLowerCase()).setTopic(topic);
+    logger.info("CommonFileStore::getFhirResourcesByTopic(): " + criteria.toString());
+
+    List<FhirResource> fhirResourceList = fhirResources.findByTopic(criteria);
+    List<FileResource> resources = readFhirResourcesFromFiles(fhirResourceList, fhirVersion, baseUrl);
+    List<FileResource> outputResources = new ArrayList<>();
+
+    if (!resources.isEmpty()) {
+      for (FileResource resource : resources) {
+        if ((resource != null) && fhirVersion.equalsIgnoreCase("r4")) {
+          FileResource processedResource = resource;
+
+          if (resourceType.equalsIgnoreCase("Questionnaire")) {
+            // If this is a questionnaire, run it through the processor to modify it before returning.
+            // We do not handle nested sub-questionnaire at this time.
+            processedResource = this.subQuestionnaireProcessor.processResource(resource, this, baseUrl);
+            processedResource = this.questionnaireValueSetProcessor.processResource(processedResource, this, baseUrl);
+            processedResource = this.questionnaireEmbeddedCQLProcessor.processResource(processedResource, null, null);
+
+          } else if (resourceType.equalsIgnoreCase("Library")) {
+            // If this is a library, process it by replacing the content url with a base64
+            // encoded version of the cql
+            // When requested via topic, do this even if flag is not set in config (embedCqlInLibrary)
+            processedResource = this.libraryContentProcessor.processResource(resource, this, baseUrl);
+          }
+
+          // add the resource to the output list
+          outputResources.add(processedResource);
+        }
+
+      }
+    }
+
+    return outputResources;
+  }
+
+  public Bundle getFhirResourcesByTopicAsFhirBundle(String fhirVersion, String resourceType, String topic, String baseUrl) {
+    List<FileResource> fileResources = getFhirResourcesByTopic(fhirVersion, resourceType, topic, baseUrl);
+    Bundle bundle = new Bundle();
+    if (fileResources != null && !fileResources.isEmpty()) {
+      for (FileResource fileResource : fileResources) {
+        if (fileResource != null) {
+          Resource resource = null;
+          try {
+            // convert the file resource into the fhir resource
+            resource = (Resource) parser.parseResource(fileResource.getResource().getInputStream());
+            BundleEntryComponent entry = new BundleEntryComponent().setResource(resource);
+            bundle.addEntry(entry);
+          } catch(IOException ioe) {
+            logger.error("Issue parsing FHIR file resource for preprocessing.", ioe);
+            return null;
+          }
+        }
+      }
+    }
+    
+    return bundle;
+  }
+
+  public FileResource getFhirResourcesByTopicAsBundle(String fhirVersion, String resourceType, String topic, String baseUrl) {
+    Bundle bundle = getFhirResourcesByTopicAsFhirBundle(fhirVersion, resourceType, topic, baseUrl);
+    if (bundle.isEmpty()) {
+      return null;
+    }
+    
+    byte[] resourceData = parser.encodeResourceToString(bundle).getBytes(Charset.defaultCharset());
+    FileResource outputFileResource = new FileResource();
+    outputFileResource.setResource(new ByteArrayResource(resourceData));
+    outputFileResource.setFilename("bundle.json");
+    return outputFileResource;
+  }
+
   // from RuleFinder
   public List<RuleMapping> findRules(CoverageRequirementRuleCriteria criteria) {
     logger.info("CommonFileStore::findRules(): " + criteria.toString());
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/files/FileStore.java b/server/src/main/java/org/hl7/davinci/endpoint/files/FileStore.java
index 56090c641..dc1c5e6b9 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/files/FileStore.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/files/FileStore.java
@@ -4,6 +4,8 @@
 
 import org.hl7.davinci.endpoint.cql.CqlRule;
 import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Resource;
 import org.hl7.davinci.endpoint.database.RuleMapping;
 import org.hl7.davinci.endpoint.database.FhirResource;
 
@@ -21,10 +23,18 @@ public interface FileStore {
 
   FileResource getFile(String topic, String fileName, String fhirVersion, boolean convert);
 
-  FileResource getFhirResourceByTopic(String fhirVersion, String resourceType, String name, String baseUrl);
+  // Get FHIR Resources as FileResource
+  FileResource getFhirResourceByName(String fhirVersion, String resourceType, String name, String baseUrl);
   FileResource getFhirResourceById(String fhirVersion, String resourceType, String id, String baseUrl);
   FileResource getFhirResourceById(String fhirVersion, String resourceType, String id, String baseUrl, boolean isRoot);
   FileResource getFhirResourceByUrl(String fhirVersion, String resourceType, String url, String baseUrl);
+  List<FileResource> getFhirResourcesByTopic(String fhirVersion, String resourceType, String topic, String baseUrl);
+  FileResource getFhirResourcesByTopicAsBundle(String fhirVersion, String resourceType, String topic, String baseUrl);
+  
+  // Get FHIR Resources as FHIR Resources
+  Resource getFhirResourceByIdAsFhirResource(String fhirVersion, String resourceType, String id, String baseUrl);
+  Resource getFhirResourceByUrlAsFhirResource(String fhirVersion, String resourceType, String url, String baseUrl);
+  Bundle getFhirResourcesByTopicAsFhirBundle(String fhirVersion, String resourceType, String topic, String baseUrl);
 
   // from RuleFinder
   List<RuleMapping> findRules(CoverageRequirementRuleCriteria criteria);
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/files/LibraryContentProcessor.java b/server/src/main/java/org/hl7/davinci/endpoint/files/LibraryContentProcessor.java
index c19108958..233995f26 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/files/LibraryContentProcessor.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/files/LibraryContentProcessor.java
@@ -6,8 +6,9 @@
 import org.hl7.fhir.r4.model.Library;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
- 
+
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -48,7 +49,7 @@ protected Library processResource(Library inputResource, FileStore fileStore, St
 
               // content is CQL (assuming elm/json is actually CQL)
               String topic = urlParts[1];
-              String fhirVersion = urlParts[2];
+              String fhirVersion = urlParts[2].toUpperCase();
               String fileName = urlParts[3];
 
               List<Attachment> attachments = new ArrayList<>();
@@ -87,8 +88,9 @@ private Attachment base64EncodeToAttachment(FileResource fileResource, String mi
     Attachment attachment = new Attachment();
     try {
       // base64 encode
-      byte[] byteData = new byte[(int) fileResource.getResource().contentLength()];
-      fileResource.getResource().getInputStream().read(byteData, 0, byteData.length);
+      InputStream inputStream = fileResource.getResource().getInputStream();  
+      byte[] byteData = new byte[inputStream.available()];
+      inputStream.read(byteData);
       String encodedData = Base64.encodeBase64String(byteData);
       attachment.setContentType(mimeType);
       Base64BinaryType b64bType = new Base64BinaryType();
@@ -100,3 +102,5 @@ private Attachment base64EncodeToAttachment(FileResource fileResource, String mi
     return attachment;
   }
 }
+
+
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/files/github/GitHubFileStore.java b/server/src/main/java/org/hl7/davinci/endpoint/files/github/GitHubFileStore.java
index 74812fd7e..965868250 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/files/github/GitHubFileStore.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/files/github/GitHubFileStore.java
@@ -316,6 +316,7 @@ public CqlRule getCqlRule(String topic, String fhirVersion) {
 
   public FileResource getFile(String topic, String fileName, String fhirVersion, boolean convert) {
     FileResource fileResource = new FileResource();
+    fhirVersion = fhirVersion.toUpperCase();
     fileResource.setFilename(fileName);
 
     String rulePath = config.getGitHubConfig().getRulePath();
diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml
index f4e8084e2..35aa7a934 100644
--- a/server/src/main/resources/application.yml
+++ b/server/src/main/resources/application.yml
@@ -50,7 +50,7 @@ urlEncodeAppContext: true
 # When this flag is true, the server will modify a FHIR Library when retrieved.
 # It will automatically retrieve, base64 encode, and embed the referenced (from url)
 # CQL into the data field of the content.
-embedCqlInLibrary: false
+embedCqlInLibrary: true
 
 cdsConnect:
   url: https://cdsconnect.ahrqstg.org
@@ -77,3 +77,5 @@ valueSetCachePath: ValueSetCache/
 
 hostOrg: default
 
+# Configure whether Query Batch Requests will be used to backfill potentially missing prefetch resources.
+queryBatchRequest: true
diff --git a/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/components/CardBuilderTest.java b/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/components/CardBuilderTest.java
index 726b2d35e..5fd37bfcb 100644
--- a/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/components/CardBuilderTest.java
+++ b/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/components/CardBuilderTest.java
@@ -7,6 +7,7 @@
 import org.hl7.davinci.endpoint.components.CardBuilder;
 import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard;
 import org.cdshooks.Card;
+import org.hl7.davinci.r4.CardTypes;
 import org.junit.jupiter.api.Test;
 
 public class CardBuilderTest {
@@ -20,7 +21,7 @@ public void testRulesWithNoAuthNeeded() {
     coverageRequirements.setInfoLink("http://some.link");
     coverageRequirements.setSummary("The summary!");
     cardResults.setCoverageRequirements(coverageRequirements);
-    Card card = CardBuilder.transform(cardResults);
+    Card card = CardBuilder.transform(CardTypes.COVERAGE, cardResults);
     assertEquals("The summary!", card.getSummary());
     assertEquals("Some details.", card.getDetail());
     assertEquals("http://some.link", card.getLinks().get(0).getUrl());
diff --git a/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/EndToEndRequestPrefetchTest.java b/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/EndToEndRequestPrefetchTest.java
index 8cd3a629c..74c0f31fb 100644
--- a/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/EndToEndRequestPrefetchTest.java
+++ b/server/src/test/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/EndToEndRequestPrefetchTest.java
@@ -3,7 +3,6 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -13,7 +12,7 @@
 import java.nio.charset.Charset;
 import org.apache.commons.io.FileUtils;
 import org.hl7.davinci.endpoint.Application;
-import org.junit.Ignore;
+import org.hl7.davinci.endpoint.config.YamlConfig;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,7 +27,6 @@
 import org.springframework.http.MediaType;
 import org.springframework.test.context.junit4.SpringRunner;
 
-
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
 public class EndToEndRequestPrefetchTest {
@@ -50,6 +48,8 @@ public class EndToEndRequestPrefetchTest {
   private int port;
   @Autowired
   private TestRestTemplate restTemplate;
+  @Autowired
+  private YamlConfig myConfig;
 
   public EndToEndRequestPrefetchTest() throws IOException {
   }
@@ -68,6 +68,8 @@ public void shouldRunSuccessfully() {
 
   @Test
   public void shouldSuccessfullyFillPreFetch() {
+    // Disable Query Batch Request since it relies on a Fhir Server or mock class.
+    myConfig.setQueryBatchRequest(false);
     stubFor(get(urlMatching(prefetchUrlMatcher))
         .willReturn(aResponse()
             .withStatus(200)
@@ -88,10 +90,11 @@ public void shouldSuccessfullyFillPreFetch() {
 
   @Test
   public void shouldFailToFillPrefetch() {
+    // Disable Query Batch Request since it relies on a Fhir Server or mock class.
+    myConfig.setQueryBatchRequest(false);
     stubFor(get(urlMatching(prefetchUrlMatcher))
         .willReturn(aResponse()
             .withStatus(404)));
-
     HttpHeaders headers = new HttpHeaders();
     headers.setContentType(MediaType.APPLICATION_JSON);
     HttpEntity<String> entity = new HttpEntity<String>(deviceRequestEmptyPrefetchJson, headers);
