51.0.1Prior Auth CRD (Coverage Requirement Discovery) Module Overview
Experimental

 
Please contact us if you would like to try out this experimental new feature.

51.0.2Prior 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.

51.0.3Prior Auth CRD (Coverage Requirement Discovery) Module Overview

 

51.0.3.1CDS 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.

51.0.3.2Processing 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 format.

51.0.3.3Camel 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 format.

51.0.3.4Camel processors

  • There is one default camel processor, for CRD use case, that is shipped with the module and can be used for default CQL engine processing.
    • Clients can use the default camel processor, named crdApplyProcessor in their camel route to use CQL engine to evaluate the prior auth request.
      • The crdApplyProcessor requires a route parameter named planDefinitionId, which will be used to perform the PlanDefinition/$apply call.
      • Example route using the default processor :
      <route>
         <from uri="direct:start"/>
         <to uri="smile:prior_auth_crd_module_id/crdApplyProcessor?planDefinitionId=plan_definition_fhir_resource_id"/>
      </route>
      

51.0.3.5CQL 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 a custom interceptor, where clients can have their own logic to determine the Patient in context.
/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
 * %%
 * All rights reserved.
 * #L%
 */

package com.smilecdr.demo.priorauthcrd;

import ca.cdr.api.fhir.interceptor.CdrHook;
import ca.cdr.api.fhir.interceptor.CdrPointcut;
import ca.cdr.api.priorauth.PriorAuthCrdContextJson;
import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Coverage;
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.ResourceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

/**
 * Sample interceptor codebase which allows getting Payer Patient ID by matching Provider and Payer Coverage resources
 * based off Identifier
 */
@SuppressWarnings({"unused"})
@Interceptor
public class PriorAuthCRDInterceptorTemplate {
	private static final Logger ourLog = LoggerFactory.getLogger(PriorAuthCRDInterceptorTemplate.class);
	private static final String IDENTIFIER_SYSTEM = "http://acme.org/fhir-ns/payer-coverage-identifier-system";

	@Autowired
	@Qualifier("paCrdDaoRegistry")
	private DaoRegistry myDaoRegistry;

	@CdrHook(CdrPointcut.PRIOR_AUTH_CRD_GATHER_CONTEXT)
	public void gatherContext(
			@Nonnull CdsServiceRequestJson theCdsServiceRequestJson,
			@Nonnull PriorAuthCrdContextJson thePriorAuthCrdContextJson) {
		ourLog.info("Interceptor PRIOR_AUTH_CRD_GATHER_CONTEXT - started");
		final Bundle coverageBundle = (Bundle) theCdsServiceRequestJson.getPrefetch("coverageBundle");
		final Identifier coverageIdentifier = getProviderCoverageIdentifier(coverageBundle);
		final String payerPatientId = getPayerPatientId(coverageIdentifier);
		thePriorAuthCrdContextJson.setPayerPatientId(payerPatientId);
		ourLog.info("Interceptor PRIOR_AUTH_CRD_GATHER_CONTEXT - ended");
	}

	/**
	 * Get the provider Coverage identifier from provider Coverage bundle found in prefetch of CDS hooks request
	 * @param theRequest the provider Coverage bundle
	 * @return provider coverage identifier
	 */
	@Nonnull
	private Identifier getProviderCoverageIdentifier(@Nonnull Bundle theRequest) {
		final Coverage providerCoverage = theRequest.getEntry().stream()
				.map(Bundle.BundleEntryComponent::getResource)
				.filter(resource -> resource.getResourceType().equals(ResourceType.Coverage))
				.map(Coverage.class::cast)
				.findFirst()
				.orElseThrow(() -> new UnprocessableEntityException("Coverage resource not found"));
		return providerCoverage.getIdentifier().stream()
				.filter(identifier -> identifier.getSystem().equals(IDENTIFIER_SYSTEM))
				.findFirst()
				.orElseThrow(() -> new UnprocessableEntityException("Identifier with specified system not found"));
	}

	/**
	 * Get the Payer Patient ID in context
	 * @param theCoverageIdentifier provider coverage identifier
	 * @return Payer Patient ID
	 */
	@Nonnull
	private String getPayerPatientId(@Nonnull Identifier theCoverageIdentifier) {
		final SearchParameterMap searchParameterMap = getSearchParameterMap(theCoverageIdentifier);
		final IFhirResourceDao<Coverage> coverageResourceDao = myDaoRegistry.getResourceDao(Coverage.class);
		final IBundleProvider search = coverageResourceDao.search(searchParameterMap, new SystemRequestDetails());
		return ((Coverage) search.getAllResources().get(0)).getBeneficiary().getReference();
	}

	/**
	 *  Build SearchParameterMap for Dao search on Coverage identifier
	 * @param theCoverageIdentifier provider coverage identifier
	 * @return SearchParameterMap
	 */
	@Nonnull
	private SearchParameterMap getSearchParameterMap(@Nonnull Identifier theCoverageIdentifier) {
		final TokenParam tokenParam =
				new TokenParam(theCoverageIdentifier.getSystem(), theCoverageIdentifier.getValue());
		final SearchParameterMap searchParameterMap = new SearchParameterMap();
		searchParameterMap.add(Coverage.SP_IDENTIFIER, tokenParam);
		return searchParameterMap;
	}
}
  • After determining the Patient in context, a request is submitted to the CQL Engine via the PlanDefinition/$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.
  • Note: Starting v2025.08, this interceptor will be removed as the Patient in context can be set in camel properties.