Prior Auth CRD (Coverage Requirement Discovery) Module Overview
EAP

 
Please contact us if you would like to try out this early access feature.

Prior Auth CRD (Coverage Requirement Discovery) Introduction

 

The Coverage Requirements Discovery (CRD) module in Smile Digital Health facilitates interactions between the Electronic Medical Record (EMR) systems, referred to as the Client, and the payer systems to determine prior authorization requirements for specific healthcare services to be provided to a patient.

Built on the Fast Healthcare Interoperability Resources (FHIR®) standards, Prior Auth CRD aligns with the HL7 Da Vinci Coverage Requirements Discovery (CRD) implementation guidelines (IG). The Prior Auth CRD module supports FHIR® version R4 and enhances the prior authorization workflow with several key features:

  • Prefetching Required Data Resources: The module depends on the CDS hooks module that can automatically fetch necessary data resources required for prior authorization.
  • Camel Integration: The module allows client to configure a camel route in order to determine prior authorization requests and their eligibility.
  • Additionally, clients may choose to use our in-built CQL Engine for Prior Authorization Determination, which utilizes Clinical Quality Language (CQL) to evaluate the prior authorization requirements alongside Provider Eligibility Checks, which insures that the provider is eligible to request the prior authorization.

Prior Auth CRD (Coverage Requirement Discovery) Module Overview

 

CDS Service Discovery

The Prior Auth CRD module registers one or more CDS services to the CDS hooks module dependency. These services are available at the discovery url of the CDS hooks module i.e. {{baseCDSHooksModuleUrl}}/cds-services. This list includes:

  • Endpoint URLs: The specific endpoints that can be accessed.
  • Required Resources: The necessary data resources that must be submitted with the order. If these resources are not provided, the module will automatically prefetch them using the provided authentication.
  • Configuration Options: Available configuration details are provided via the davinci-crd.configuration-options extension.

Processing Hook Request

  • The client sends a request containing the necessary fields for prior authorization.
  • The request is then sent to the camel route that is configured in the module itself for further evaluation.
    • Clients can configure JS functions or custom Java processors/endpoints/components, which can be used in camel routes.
  • The module then converts the response at the end of camel exchange and sends it back to the user. Note:The outcome of the camel process is expected to be a CdsServiceResponseJson as a Java object or in a String or Stream format.

Camel processing

  • Starting v2025.05, camel route will be used for evaluation of a prior auth request.
  • The camel context contains :
    • Request Body: The camel exchange body.
    • PriorAuthCrdContextJson: This contains additional context for the request. This object is passed as a camel exchange property with key priorAuthCrdContextJson.
  • At the end of the exchange, the module expects the exchange to return CdsServiceResponseJson as a Java object or in a String or Stream format.

Camel processors

  • There are two default camel processors for CRD use case that are shipped with the module and can be used for CQL engine processing:
    • crdToCqlRequestProcessor: Prepares the PlanDefinition/$apply request by:
      • Validating the CRD context configuration
      • Determining the patient from the payer system using coverage identifier
      • Creating the FHIR Parameters resource for the $apply operation
    • cqlToCrdResponseProcessor: Processes the PlanDefinition/$apply response by:
      • Parsing the Parameters response from the $apply operation
      • Extracting the result bundle
      • Converting it to a CDS Hooks response format
    • Both processors require PriorAuthCrdContextJson to include configurations using the property crdApplyProcessorConfig on PriorAuthCrdContextJson.
  • There are also two optional davinci-crd.configuration extension camel processors that can apply the max-cards and coverage-info extensions.
    • crdDaVinciMaxCardsProcessor: Applies the requested max-card value or the default configured in the CDS Hook Definition.
    • crdDaVinciCoverageInfoProcessor: Applies the requested coverage-info value or the default configured in the CDS Hook Definition.
    • If you add these DaVinci Extension processors, you must also ensure the extensions are configured in your CDS Hook Definitions.
      • Example route using the default processors:
        <route>
           <from uri="direct:start-crd"/>
           <!-- Prepare the $r5.apply request -->
           <to uri="smile:prior_auth_crd_module_id/crdToCqlRequestProcessor"/>
           <!-- Marshal to FHIR JSON -->
           <marshal>
              <fhirJson/>
           </marshal>
           <!-- Make the HTTP call to PlanDefinition/$r5.apply -->
           <setHeader name="CamelHttpMethod">
              <constant>POST</constant>
           </setHeader>
           <setHeader name="Content-Type">
              <constant>application/json</constant>
           </setHeader>
           <to uri="<base-fhir-endpoint>/PlanDefinition/<planDefinitionId>/$r5.apply"/>
           <!-- Process the $apply response -->
           <to uri="smile:prior_auth_crd_module_id/cqlToCrdResponseProcessor"/>
           <!-- Apply DaVinci CRD Extension Processing (Optional) -->
           <to uri="smile:prior_auth_crd/crdDaVinciMaxCardsProcessor"/>
           <to uri="smile:prior_auth_crd/crdDaVinciCoverageInfoProcessor"/>
        </route>
        

Camel Error Handling

When using Camel routes for evaluating prior auth requests, it is important to consider error handling.

In the example above, the routing to <base-fhir-endpoint>/PlanDefinition/<planDefinitionId>/$r5.apply is an upstream http request that could fail for a variety of reasons - network, configuration etc.

Upstream errors should be trapped in your route definitions and converted to an exception type that derives from ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException. This way, the error will be properly trapped and handled with a clear message back to the calling client.

Example of simple error handling in a Camel Route:

<route>
	<from uri="direct:start-crd"/>
	<doTry>
		<to uri="<base-fhir-endpoint>/PlanDefinition/<planDefinitionId>/$r5.apply"/>
		<doCatch>
			<exception>org.apache.camel.http.base.HttpOperationFailedException</exception>
			<!-- This is a simple example that just passes the response body. -->
			<throwException exceptionType="ca.uhn.fhir.rest.server.exceptions.InternalErrorException" message="${exception.responseBody}"/>
		</doCatch>
	</doTry>
</route>

If you have a lot of routes, and want to reduce the <doTry><doCatch> boilerplate, you can use <onException>

<route id="my-error-handling-route">
	<from uri="direct:my-error-handling-route"/>
	<!-- Any desired error handling logic can go here, and be re-used in specific routes -->
	<throwException exceptionType="ca.uhn.fhir.rest.server.exceptions.InternalErrorException" message="${exchangeProperty.CamelCaughtException.responseBody}"></throwException>
</route>
<route id="my-prior-auth-route">
	<onException>
		<exception>org.apache.camel.http.base.HttpOperationFailedException</exception>
		<to uri="direct:my-error-handling-route"/>
		<!--
			handled=true marks the exchange as successfully handled despite the error.	
			Only use this when you have, or will be, transforming the error into a proper response.
			In this example, the error will be converted in "my-error-handling-route"
		-->
		<handled><constant>true</constant></handled>
	</onException>

	<from uri="direct:start-crd"/>
	<!-- Rest of route logic including upstream http or broker calls-->
</route>

If using <onException> instead of <doCatch> be aware that the ${exception} value is no longer available. You will need to access it through the ${exchangeProperty.CamelCaughtException} exchange property.

If your routing is simple, <doTry><doCatch> might be better choice. If you have many routes, <onException> can help reduce the route boilerplate and centralize error handling.

CQL Engine Supported CDS Hooks

The CRD flow has been tested with CQL PlanDefinition resource configuration supporting the following orders.

  • order-sign — triggered when an order is signed or authorized.
  • order-dispatch — triggered when an order is dispatched for fulfillment.
  • appointment-book — triggered when an appointment is being scheduled.
  • order-select — triggered when an order is selected.

Support for additional CDS Hooks may require corresponding updates to the CQL processing logic and the underlying CQL rules to handle the specific hook context and request payload.

CQL Engine Processing

  • The system determines the Patient in context by expecting the member ID to be present as Coverage identifier and use this to match the Patient.
    • This behaviour can be overridden by setting patientId in PriorAuthCrdContextJson inside Camel context, where clients can have their own logic to determine the Patient in context.
  • After determining the Patient in context, a request should be submitted to the CQL Engine via the PlanDefinition/$r5.apply operation.
  • The CQL Engine evaluates the business logic and determines whether the requested service requires prior authorization. It then returns a response containing the authorization determination.
  • The Prior Auth CRD module processes the response from the CQL Engine and returns it to the client, providing the necessary coverage eligibility information and prior authorization status.
  • The following example shows an interceptor that can be used as a starter Prior Auth CRD interceptor, implementing a hook method for available pointcut.

Stateless Vs Stateful CDS Engine Processing

Some CDS Engines will manage state, and allow a continuation between the CRD and DTR flows by only passing the coverage-assertion-id. Others will be stateless, and have no memory or caching between the CRD and DTR flows. In these cases, Smile can be configured to maintain state and correlate the DTR $questionnaire-package operation back to the initial CRD evaluation.

The first step for this configuration is to ensure your stateless camel routes are configured with the crdCoverageAssertionIdGenerator Camel Processor. See the route example below.

The second step is to prepare and configure the cache details and the supporting cache processor. This involves using the crdCacheGenerator Camel Processor after setting a few Camel Exchange properties.

To configure the cache a few Camel Exchange properties need to be set:

Exchange Property NameDescription
paCrdResponseCacheA map of order specific cache details. See below.
paCrdCacheBaseFhirStorageUrlThe base url of the FHIR Endpoint at which to cache the response details.
paCrdCacheBaseFhirStorageAuthAn auth header (including Basic/Bearer etc) for the FHIR Endpoint

The priorAuthCrdResponseCache is a map made up of a composite set of values keyed to each order id. The values are:

  • coverageAssertionId - The unique id generated by the upstream CRD engine or the configured crdCoverageAssertionIdGenerator
  • delegate - A unique key to mark which upstream engine this request should be evaluated by.
  • questionnaireCanonicals - 0..* Questionnaire Canonical URLs associated with the order.
function preparePriorAuthCrdCache(message, exchange) {
  const cacheMap = {};

  // exchange orders or system actions from the message
  for (const order of orders) {

    // logic to extract details from the response

    // once we have the order specific details, we add it to the cache
    cacheMap[order.id] = {
      coverageAssertionId,
      delegate: 'MY-UPSTREAM-CRD-EVALUATION-ENGINE',
      questionnaireCanonicals
    };
  }

  // Then we add the details to the exchange property
  exchange.properties['paCrdResponseCache'] = JSON.stringify(cacheMap);

  // We configure the base URL of where the cache should be stored
  exchange.properties['paCrdCacheBaseFhirStorageUrl'] = 'https://my-cache-server/'

  // And how it should authenticate
  exchange.properties['paCrdCacheBaseFhirStorageAuth'] = getCacheAuthHeader();
}

<route>
  <from uri="direct:stateless-crd-route"/>
  
  <to uri="https://mystateless-crd-engine/path/to/evaluation/endpoint"/>

  <!-- Ensure that a unique coverage-assertion-id is generated -->
   <to uri="smile:prior_auth_crd/crdCoverageAssertionIdGenerator"/>

   <!-- Configure our cache, and add the caching processor -->
   <to uri="smile:camel/script?function=preparePriorAuthCrdCache&amp;includeExchange=true"/>
   <to uri="smile:prior_auth_crd/crdCacheGenerator"/>

  <!-- Apply DaVinci CRD Extension Processing (Optional) -->
  <to uri="smile:prior_auth_crd/crdDaVinciMaxCardsProcessor"/>
  <to uri="smile:prior_auth_crd/crdDaVinciCoverageInfoProcessor"/>
</route>

Notes About crdCoverageAssertionIdGenerator

  • This processor will only generate a coverage-assertion-id if one is not already existing.
  • The format of the coverage-assertion-id is v4 UUID (e.g. bce10943-ec62-4c66-94e8-fd1417586548)
  • A distinct coverage-assertion-id is generated for each ext-coverage-information extension present in the CDS Engine response.