On this page:



CDS-Hooks are services called by CDS Clients (typically Electronic Health Record Systems (EHRs) or other health information systems). They implement a "hook"-based pattern for invoking decision support from within a clinician's workflow.

Smile CDR implements Version 1.1 of the CDS-Hooks Specification.

The Smile CDR CDS-Hooks Module simplifies the effort for creating CDS-Hooks. All you need to do is create a method that accepts a CdsServiceRequestJson parameter and returns a CdsServiceResponseJson value and annotate this method with the @CdsService annotation. This annotation, and the Json classes and all their subcomponents are available in the open-source project called cdr-api-public. Any FHIR resources in requests and responses are automatically serialized into hapi-fhir FHIR resource instances for you so they are easy to work with within your code.

In addition to simplifying the effort to build CDS-Hooks, the Smile CDR CDS-Hooks module also provides the following:

  • All access is logged in the Smile CDR Audit Trail.
  • Authorization is controlled by the Smile CDR security framework.
  • Management and monitoring capabilities are provided by the Smile CDR platform.

15.0.1Auto Prefetch


The Smile CDR CDS-Hooks module provides a couple of powerful Auto-Prefetch features:

  1. If allowAutoFhirClientPrefetch is set to true in the @CdsService annotation on your CDS Service method, then before calling your method, Smile CDR will compare the prefetch elements declared by your service method in the @CdsService annotation to the prefetch elements included within the CdsServiceRequestJson REST request and if it detects any are missing, then Smile CDR will use the FHIR endpoint authorization details included within the fhirAuthorization element in the request to automatically add them to the prefetch before calling your method.
  2. Even simpler, if your Smile CDR server has a FHIR Storage module, you can optionally add a dependency from your CDS-Hooks Module on your FHIR Storage module. If you do this, then when Smile CDR detects any required prefetch elements missing in a request, it will automatically fetch the missing data from your storage module before calling your CDS-Hooks method. Note in this case, the same credentials used to call the CDS-Hooks endpoint are used to authorize access to the FHIR Storage module.

CDS-Hooks Auto Prefetch Rules

  • If there are no missing prefetch elements, the CDS-Hooks service method is called directly with the request. (Note that per the CDS-Hooks specification, a value of null is not considered to be missing. CDS-Hooks clients set a prefetch value to null to indicate that this prefetch data is known to not exist).
  • Otherwise, if a fhirServer is included in the request
    • If the @CdsService annotation on the service method has allowAutoFhirClientPrefetch = true, then Smile CDR will perform a FHIR REST call to that fhirServer endpoint to fetch the missing data.
    • otherwise, the CDS-Hooks service method is expected to call the fhirServer endpoint itself to retrieve the missing data.
  • Otherwise, if the CDS-Hooks Module declares a dependency on a FHIR Storage Module, then Smile CDR will fetch the missing data from that FHIR Storage Module.
  • Otherwise the method will fail with HTTP 412 PRECONDITION FAILED (per the CDS-Hooks specification).



The diagram below shows how CDS-Hooks work. The box in grey contains customer code, which is code that you write.

CDS-Hooks Architecture

A CDS-Hooks implementation is packaged as a Java JAR file that contains several key components:

  • CDS Service classes, which implement CDS-Hooks service and feedback methods.
  • A Spring Context Config class, which is a Spring Framework class used to instantiate and configure the CDS-Hooks classes.

15.0.3CDS-Hooks classes


A CDS-Hooks class contains annotated service and feedback methods. One CDS-Hooks class can contain any number of these methods. A CDS-Hooks service method is annotated with the @CdsService annotation and a CDS-Hooks feedback method is annotated with the @CdsServiceFeedback annotation. The "value" of these annotations corresponds to the id of the CDS-Hooks service. For example:

A method annotated with @CdsService(value="example-service") is acccessed at a path like https://example.com:8888/cds-services/example-service

A method annotated with @CdsServiceFeedback(value="my-service") is acccessed ata path like https://example.com:8888/cds-services/my-service/feedback.

A very basic example is shown below:

package ca.cdr.endpoint.cdshooks.module;

import ca.cdr.api.cdshooks.CdsService;
import ca.cdr.api.cdshooks.CdsServiceFeedback;
import ca.cdr.api.cdshooks.CdsServicePrefetch;
import ca.cdr.api.cdshooks.json.CdsServiceFeedbackJson;
import ca.cdr.api.cdshooks.json.CdsServiceIndicatorEnum;
import ca.cdr.api.cdshooks.json.CdsServiceRequestJson;
import ca.cdr.api.cdshooks.json.CdsServiceResponseCardJson;
import ca.cdr.api.cdshooks.json.CdsServiceResponseCardSourceJson;
import ca.cdr.api.cdshooks.json.CdsServiceResponseJson;
import org.hl7.fhir.r4.model.Patient;

public class ExampleCdsService {
   @CdsService(value = "example-service",
      hook = "patient-view",
      title = "Greet a patient",
      description = "This service says hello to a patient",
      prefetch = {
         @CdsServicePrefetch(value = "patient", query = "Patient/{{context.patientId}}")
   public CdsServiceResponseJson exampleService(CdsServiceRequestJson theCdsRequest) {
      Patient patient = (Patient) theCdsRequest.getPrefetch("patient");
      CdsServiceResponseJson response = new CdsServiceResponseJson();
      CdsServiceResponseCardJson card = new CdsServiceResponseCardJson();
      card.setSummary("Hello " + patient.getNameFirstRep().getNameAsSingleString());
      CdsServiceResponseCardSourceJson source = new CdsServiceResponseCardSourceJson();
      source.setLabel("Smile CDR");
      return response;

   public String exampleServiceFeedback(CdsServiceFeedbackJson theFeedback) {
      return "{\"message\": \"Thank you for your feedback dated " + theFeedback.getOutcomeTimestamp() + "!\"}";

Both of these example methods accept a single json instance parameter (CdsServiceRequestJson and CdsServiceFeedbackJson respectively). Alternatively, these methods can accept a single String parameter in which case the CDS-Hooks module will string-encode the instance before calling the method.

15.0.4The Spring Context Config Class


This mandatory class is a Spring Framework Annotation-based Application Context Config class. It is characterized by having the @Configuration annotation on the class itself, as well as having one or more non-static factory methods annotated with the @Bean method, which create instances of your providers (as well as creating any other utility classes you might need, such as database pools, HTTP clients, etc.).

This class must instantiate a bean named cdsServices:

  • The cdsServices bean method should return a List<Object> of classes that contain @CdsService and/or @CdsServiceFeedback annotated methods.

The following example shows a Spring Context Config class that registers the CDS-Hooks example above.

public class TestServerAppCtx {

    * This bean is a list of CDS-Hooks classes, each one
    * of which implements one or more CDS-Hook Services.
   @Bean(name = "cdsServices")
   public List<Object> cdsServices(){
      List<Object> retVal = new ArrayList<>();
      retVal.add(new ExampleCdsService());
// add other CDS-Hooks classes...
      return retVal;

15.0.5Building Your CDS-Hooks


This section outlines considerations when buiding your CDS-Hooks classes.

In order to build your Smile CDR CDS-Hooks, you will need the annotation and json classes on your path. Currently this is accomplished by adding the cdr-public-api-*.jar file to your build classpath. This jar file can be found in your smilecdr/lib folder. In the future, this jar will be published to a central repository and available as a maven dependency.

See Library Support for details concerning libraries available on the classpath where your CDS-Hooks classes are loaded.

Packaging Your Providers

The Spring Context Config class and your CDS-Hooks classes must all be packaged up in a normal Java JAR file. No third party libraries should be packaged with your code.

If you are using Apache Maven as your build system, this just means you should use a normal project with a packaging of jar.

15.0.6Deploying Your CDS-Hooks


Once you have created a JAR with your CDS-Hooks in it, this JAR should be placed in the customerlib/ directory of the Smile CDR installation, and Smile CDR should be restarted. You will then want to create a new module configuration as follows:

  1. Log into the Web Admin Console.
  2. Navigate to the Module Config section ( Config -> Module Config ).
  3. Create a new module of type CDS-Hooks Endpoint.
  4. Give the module a sensible ID.
  5. Under Listener Port, enter a port that the server will listen on.
  6. Under Spring Context Config Class, enter the fully qualified class name for your Spring Context Config Class.
  7. Under FHIR Version, enter the FHIR version that is used by your CDS-Hooks clients. Any resources included in CDS-Hooks requests (e.g. in context or prefetch) will be deserialized into hapi-fhir IBaseResource objects according to this FHIR Version.

15.0.7Accessing Security Attributes


CDS-Hooks methods have access to the underlying authenticated user session if needed. See Security Attributes for more information.



See Exceptions for details concerning exceptions and error management within CDS-Hooks classes.

15.0.9Calling CDS-Hooks


Per Version 1.1 of the CDS-Hooks Specification, a list of all registered services is available at a path like https://example.com:8888/cds-services. As a convenience, swagger REST documentation is provided at the root of the endpoint: https://example.com:8888/.

15.0.10Example Project


A sample CDS-Hooks project is available at the following links: