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:
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:
davinci-crd.configuration-options extension.JS functions or custom Java processors/endpoints/components, which can be used in camel routes.Java object or in a String or Stream format.v2025.05, camel route will be used for evaluation of a prior auth request.priorAuthCrdContextJson.Java object or in a String or Stream format.crdToCqlRequestProcessor: Prepares the PlanDefinition/$apply request by:
$apply operationcqlToCrdResponseProcessor: Processes the PlanDefinition/$apply response by:
$apply operationPriorAuthCrdContextJson to include configurations using the property crdApplyProcessorConfig on PriorAuthCrdContextJson.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.<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>
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.
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.
patientId in PriorAuthCrdContextJson inside Camel context, where clients can have their own logic to determine the Patient in context.PlanDefinition/$r5.apply operation.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 Name | Description |
|---|---|
paCrdResponseCache | A map of order specific cache details. See below. |
paCrdCacheBaseFhirStorageUrl | The base url of the FHIR Endpoint at which to cache the response details. |
paCrdCacheBaseFhirStorageAuth | An 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 crdCoverageAssertionIdGeneratordelegate - 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&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
coverage-assertion-id if one is not already existing.coverage-assertion-id is v4 UUID (e.g. bce10943-ec62-4c66-94e8-fd1417586548)coverage-assertion-id is generated for each ext-coverage-information extension present in the CDS Engine response.