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

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

46.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 can automatically fetch necessary data resources required for prior authorization.
  • CQL Engine for Prior Authorization Determination: Utilizes Clinical Quality Language (CQL) to evaluate the authorization requirements.
  • Provider Eligibility Checks: Ensures that the provider is eligible to request the prior authorization.

The module uses CDS Hooks to register as an endpoint service on the server and consists of several components:

  1. Registration as a CDS Service: The module registers and becomes discoverable via the CDS Hooks Discovery Endpoint.
  2. Support for CDS Hooks Requests: Specifically handles order-sign requests.
  3. CQL Determination Engine: Processes the business logic for authorization.
  4. Response Handling: Returns coverage eligibility information based on the authorization determination.

46.0.3Prior Auth CRD (Coverage Requirement Discovery) Module Overview

 

46.0.3.1CDS Service Discovery

The Prior Auth CRD module registers itself as a CDS Service. Accessing the endpoint at {{baseUrl}}/cds-services will return a list of endpoints for the available services. The Prior Auth CRD will be listed among the CDS Services on the discovery endpoint. 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.

46.0.3.2Processing Hook Request

  • The client sends a request containing the necessary fields for prior authorization.
  • 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.
    • The following example shows an interceptor that can be used as a starter Prior Auth CRD interceptor, implementing a hook method for available pointcut.
/*-
 * #%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 PlanDef/$apply operation.

46.0.3.3CQL Engine Processing

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.

46.0.3.4Returning Response

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.