
What Is Prior Authorization? What Is Changing in 2027?
What prior authorization is, why the process has been so slow, and what CMS-0057-F and HTI-4 require health plans to fix by January 2027.
September 24, 2026
CMS-0057-F requires health plans to run a Prior Authorization API by January 1, 2027. In practice that API is three Da Vinci implementation guides that hand work to each other. Our earlier article on what prior authorization is and what changes in 2027 covers the rule and what each API does at the workflow level. This one is for the people building it, so it goes through what each API actually exchanges, where one hands off to the next, and the rules around authentication, versions, response times, and testing that apply while you build.
$questionnaire-package and $next-question, that return questionnaires along with CQL logic the EHR uses to pre-fill answers from the chart.Claim/$submit operation that takes a FHIR Bundle and returns a ClaimResponse. Pended requests are followed up through FHIR Subscriptions.These three guides aren’t built the same way. CRD runs on CDS Hooks, which has its own JSON request and response format outside FHIR REST. DTR and PAS are both FHIR operations, but DTR is mostly the EHR pulling content from the payer, while PAS is the EHR pushing a request and waiting for a decision.
| CRD | DTR | PAS | |
|---|---|---|---|
| Built on | CDS Hooks | FHIR operations, SDC questionnaires, CQL | FHIR operations, mapped to X12 278 |
| Payer exposes | /cds-services and one endpoint per hook | $questionnaire-package, $next-question, ValueSet/$expand | Claim/$submit, Claim/$inquire, Subscription |
| Triggered by | A clinician action in the EHR | A questionnaire reference from CRD, or a PAS request for more information | A completed request, usually after DTR |
| Response target | 5 seconds, 10 in some cases | None stated at this level | 15 seconds, otherwise pended |
| Current version | 2.2.1 | 2.2.0 | 2.2.1 |
| Inferno suites | 2.0.1 and 2.2.1 | 2.0.1 and 2.2.0 | 2.0.1 and 2.2.1 |
The PAS guide says clients and servers supporting PAS should comply with CRD and DTR, so even though each guide can be read on its own, they were written with the expectation that you’re implementing the set.
A CRD server starts with discovery. The EHR makes a GET request to /cds-services, and the payer answers with the hooks it supports, the prefetch it wants for each one, and two extensions that plain CDS Hooks doesn’t have. The first is the version extension, davinci-crd.version, which advertises the CRD versions your server speaks. The second is davinci-crd.configuration-options, which tells the client what kinds of responses you can return and lets it switch some of them off.

The hooks a payer has to support are appointment-book, order-sign, and order-dispatch. order-select is optional, and we recommend supporting it anyway, since it’s close to order-sign and lets the clinician see coverage requirements while they’re still choosing the order. encounter-start and encounter-discharge are optional too.
On the response side, CRD defines eight response types, and only one of them is required. The coverage information response is the one thing you have to implement for every primary hook, and everything else is optional. It goes back as a system action, which means the EHR writes it onto the order or appointment without the clinician clicking anything, and it carries whether the service is covered, whether prior auth is needed, what documentation is needed, and optionally a link to a questionnaire. The course goes through all eight response types and runs each one live against Inferno.
That questionnaire link is the handoff to DTR. The Request Form Completion response, which asks the EHR to create a Task pointing at a questionnaire, can’t be used when DTR applies and both sides support it. The Launch SMART Application response can’t be used to launch DTR at all any more, and neither the External Reference nor the Instructions card can send a user to a portal to start a prior authorization or check coverage. All of that now goes through the coverage-information extension.
Once the EHR has a questionnaire reference, it calls the payer’s $questionnaire-package operation. The Bundle that comes back has to carry the Questionnaire as its first entry, every CQL library it references, and every value set it uses, with each library included in both its CQL and compiled ELM forms and small value sets (under 40 entries) already expanded. When DTR is launched from CRD, the context for the request comes from the coverage-information extension, which is why it’s worth getting that extension right on the CRD side first.
The CQL makes pre-population work. DTR builds on the Structured Data Capture guide for the forms themselves and uses CQL for the logic that populates answers and occasionally controls the flow of questions. The EHR, or a SMART app acting for it, runs that logic against the patient’s record so the clinician only sees the questions the record couldn’t answer. Rendering can happen in a SMART on FHIR app or in functionality built into the EHR.
For forms where the next question depends on the previous answer, DTR supports adaptive questionnaires through $next-question, which it takes from the SDC guide. The payer decides the next question on each call, so the branching logic stays on the payer’s side and never ships to the EHR.
The CRD guide also draws a line between the two. It says a server should query whatever data it needs for a coverage decision when the EHR can supply it, and that relying only on DTR to collect data is not acceptable, because DTR is for information that needs a human to supply or review it. A questionnaire that asks the clinician for things your server could have fetched during the hook is the pattern the guide rules out.
The PAS request is a Bundle POSTed to [base]/Claim/$submit, encoded in JSON, with a Claim resource as the first entry and every resource it references included alongside it. FHIR uses Claim for prior authorization as well as for billing, distinguished by Claim.use, so the profiles read like claims profiles even though nothing is being billed. The QuestionnaireResponse from DTR goes in as supporting information, referenced from Claim.supportingInfo, and that’s the second handoff in the chain.
The PAS guide was written on the assumption that an X12 278 sits somewhere behind the endpoint. Whatever receives the Bundle converts it to a 278, sends it to the payer’s system, and converts the 278 response back into a FHIR Bundle that starts with a ClaimResponse. Everything past the operation endpoint is treated as a black box that can include clearinghouses and other intermediaries. The 2.2.1 text also notes that with the CMS enforcement discretion, a payer might process the FHIR content directly and skip the X12 conversion.
On timing, the whole round trip should complete synchronously within 15 seconds, including network time. When a decision can’t be made that fast, the response comes back with one or more items pended (the guide’s term for held for further review), and whether an item is approved, denied, or pended is read from the review action code on the ClaimResponse item’s adjudication.
For pended requests, the client has to use subscriptions to hear about updates. These are R4 subscriptions from the Subscriptions R5 Backport guide, over the rest-hook channel, with full-resource content, and they’re created once per sending system using an org-identifier filter, so you don’t create one per request. Claim/$inquire exists as well, but the inquiry response can’t carry everything a full response can, such as a request for additional information, so the guide tells clients not to poll while a request is still pended. It’s there for systems that can’t subscribe, like the rendering provider checking on a request they didn’t submit.
Changes to a submitted request also go through $submit, using a Claim Update as the first Bundle entry, and a denied request can’t be updated, so a new request has to be started. Servers can reject an update and require a fresh request.
For CRD, authentication comes from CDS Hooks. Every call from the EHR carries a JWT as a bearer token, signed with the EHR’s private key. When you onboard an EHR, you collect its JWKS URL, and on every request you check the signature against those keys. The jku header on the token names the key set it claims to come from, which is how you work out who is calling before you check them against the list you onboarded. We use the jose library for this and return a 401 when the token is missing or doesn’t validate. The full setup is in the lesson on discovery, TLS, and JWT validation.
TLS is required. Mutual TLS is permitted by the CRD guide and not required, so we recommend going with JWT unless a specific customer asks for mTLS, since JWT is the path the test tooling and most EHRs support. Inferno checks the TLS requirement before anything else, and a plain localhost server fails the first tests on that alone, so we put ngrok in front of the local server while testing.
Every hook request also carries a second token, fhirAuthorization, which is easy to confuse with the first. It’s an access token the EHR gives your server so it can query the EHR’s FHIR API. The guide says these tokens should expire within 30 seconds, and that they shouldn’t be forwarded to systems outside your organization unless a business associate agreement allows centralized audit of access. If you delegate decisions to utilization management vendors, this decides your architecture, because the vendor can’t call the EHR with your token. Either you route their queries through a FHIR endpoint you host, or you lean on prefetch so they don’t need to query at all.
[IMAGE: a hook request with the two tokens labelled, the JWT in the Authorization header and the fhirAuthorization token in the body]
Caption: The JWT proves who is calling you. The fhirAuthorization token lets you call them back.
DTR and PAS don’t reuse the CDS Hooks JWT scheme, because they’re FHIR APIs. Both guides defer to the HRex security rules, which set the TLS baseline and list the mechanisms an implementer can choose from without mandating one. In practice, the Inferno DTR suites require SMART Backend Services, where the client signs a token request with keys from its own JWKS and sends the resulting access token as a bearer token, and the PAS server suite works the same way if your endpoints need OAuth. You’ll still be handling JWKS URLs during onboarding, but the token exchange is a different one from CRD’s.
CMS-0057-F recommends the 2.0.1 guides for CRD and PAS and 2.0.0 for DTR. HTI-4 certifies EHRs to 2.0.1 for all three. DTR 2.0.1 was published on January 11, 2024, six days before the CMS rule, which is why the two rules name different DTR patch versions. In June 2026, ONC’s Standards Version Advancement Process added CRD 2.2.1, DTR 2.2.0, and PAS 2.2.1 as versions EHR vendors can certify to instead, starting August 29, 2026. So an EHR calling you in 2027 may be on either line. We recommend building against 2.2.1 for CRD and PAS and 2.2.0 for DTR, and adding 2.0.1 only if someone who depends on you needs it.
In CRD, a server can speak more than one version at once. In discovery, davinci-crd.version lists what the server supports, per hook, using only the first two parts of the version number (2.0, 2.1, or 2.2, never a patch number). In the hook request, the client sends davinci-crd.requestedVersion to say which version it wants, and it has to send it whenever you advertise more than one for that hook. People mix the two up because the names are so similar, but they travel in opposite directions, and the requested version is what lets you route an incoming call to the right logic when you support more than one. We cover this in the lesson on version negotiation and configuration options.
The CRD guide sets a specific rule here. Servers have to respond within the target time for 90% of calls. The target is 5 seconds for most hooks, and it extends to 10 seconds for appointment-book, and for order-sign and order-dispatch calls that arrive at least 24 hours after the last hook for the same patient and ordering organization, since nothing could have been cached in those cases. If the window passes, the EHR is allowed to abandon the call or handle the response asynchronously, and EHRs have to give clinicians a way to bypass a CRD call that’s running long.
We treat 5 seconds as the rule to design around, and with caching we’ve answered within a second in a lot of cases, which we cover in the lesson on CDS Hooks and CRD. Whatever you aim for internally should sit well under the guide’s target, because the clock runs on the EHR’s side and has to cover the network, your facade, and any vendor you call behind it.
When the time isn’t enough for a full answer, there is a fallback the guide accepts. Its own example is a server that can confirm within the window that a service is covered but can’t yet say whether prior authorization is needed. It can return the coverage answer with a doc-needed flag pointing to DTR, and let DTR and the later stages of adjudication settle the rest. A determination that more information is needed counts as a valid response.
Prefetch is how you avoid calling back into the EHR during those 5 seconds. In discovery you declare, per hook, the FHIR queries you want resolved and sent along with every call. The CRD guide publishes standard prefetch templates for each hook, and in 2.2.1, both clients and servers have to support prefetch. The templates are long, and the guide requires servers to use the published expressions for any data they rely on, so copy them as written rather than writing your own.
The guide also draws a line around what belongs in prefetch. Prefetch should hold what you need on every invocation, and data you only need for certain services or medications should be fetched with a query using the access token.
HTTP 412 is the error for when this breaks down, and it has a narrow meaning. It’s for the case where the prefetch you asked for wasn’t provided and your server couldn’t run the queries itself. It can’t be used when the data arrived but the record was missing something your rules wanted, and the preferred route for missing information is to ask for it through DTR. The same goes for other error codes, which are meant for technical failures in the service, not for unmet business rules.
If you sit in front of several vendors, each with its own prefetch needs, we recommend namespacing their keys in your aggregated discovery response, for example vendor1_p1, and stripping the prefix when you forward the hook to that vendor. The guide allows this: clients aren’t supposed to rely on standard key names, and have to take the exact keys from your discovery response.
The guide encourages payers to use hooks that fire earlier in the workflow to start caching, even when the server returns nothing for those hooks. An encounter-start call is a chance to load the member’s coverage and plan limits, and an order-select call is a chance to load the rules for the service being ordered, so that by order-sign most of what’s needed is already in hand. This is the practical reason to support the optional hooks.

On the EHR side, clients in an automated setup should re-run discovery at least once a day, and should re-run it before giving up when a hook call fails. Plan on changes to your discovery response taking up to a day to reach every client.
Inferno has a test kit for each guide on inferno.healthit.gov. The CRD and PAS kits have suites for 2.0.1 and 2.2.1. The DTR kit has 2.0.1 suites and 2.2.0 client and payer server suites, and its maintainers describe the 2.0.1 suites as immature compared to 2.2.0 and no longer being actively enhanced.
For CRD, Inferno plays the EHR and makes hook calls against your server, looking for conformant handling of each hook and for examples of each response type. You supply the request bodies it sends, since the business logic behind a response is outside the spec, so the server is only exercised on the cases you choose to give it. The kit’s own documentation calls these tests a draft meant for preliminary checks. The DTR server tests leave some requirements out, including validation of CQL content, which is where a mistake is most likely to go unnoticed.
The CRD guide has a conformance details page listing every requirement for a server, and Inferno publishes requirements spreadsheets for the kit showing which of them it tests. A lot aren’t covered, which we go through at the end of the lesson on hooks. Inferno is a good way to find out that your discovery response is missing an extension, but it doesn’t tell you whether your coverage answers are accurate.

Caption: The Inferno Discovery group on a server missing the configuration-options extension and prefetch.
The 90% response time rule, the requirement to retain logs of every hook invocation and response, and the requirement that CRD guidance be as accurate as what a provider would get by portal or phone are left for you to meet without a test checking them.
Most health plans we talk to don’t make every coverage decision in-house, and the question we hear most is what their vendors should build. We recommend that every vendor implement the unmodified CRD spec and test against Inferno themselves, while the health plan runs a facade that aggregates discovery, namespaces prefetch, and keeps the EHR’s token inside its own boundary.

The course covers this architecture in detail. We don’t have the same hands-on depth with DTR and PAS delegation yet, and the CRD guide itself says there isn’t much experience with delegated access under these timing constraints and that implementers should expect to negotiate how it works, so plan on that with your partners.
CRD is what an EHR calls first, and it’s the piece you can have running against a real test kit before anything else.
Our free course is 8 lessons and about 2 hours. It builds a CRD server in TypeScript, from discovery, TLS, and JWT validation through version and configuration extensions, prefetch, every response type, and every hook, tested live against the Inferno CRD 2.2.1 suite. The code is on GitHub [CHECK]. DTR and PAS modules are planned, so if you finish the course and there’s something you needed that it didn’t cover, tell us and it’ll shape what we record next.
Under CMS-0057-F, it's an API a health plan exposes so an EHR can find out whether a service needs prior authorization, what documentation is required, and submit the request and receive the decision electronically. CMS recommends the Da Vinci CRD, DTR, and PAS guides as the way to build it.
Coverage Requirements Discovery is the Da Vinci guide that lets an EHR ask a payer, at the moment a clinician books an appointment or signs an order, whether a service is covered and whether it needs prior authorization. It runs on CDS Hooks rather than FHIR REST, and the answer comes back as a coverage-information system action the EHR writes onto the order.
Documentation Templates and Rules is the Da Vinci guide for delivering payer questionnaires to the EHR. The payer returns a package with a Questionnaire, CQL libraries, and value sets, and the EHR uses the CQL to pre-fill answers from the patient's record before the clinician sees the form.
Prior Authorization Support is the Da Vinci guide for submitting the request itself. The EHR posts a Bundle containing a Claim to Claim/$submit and gets back a ClaimResponse, and pended requests are followed up through FHIR Subscriptions.
CMS-0057-F names 2.0.1 for CRD and PAS and 2.0.0 for DTR, but ONC's 2026 SVAP lets EHR vendors certify to CRD 2.2.1, DTR 2.2.0, and PAS 2.2.1 from August 29, 2026. We recommend building to the 2.2 line and supporting 2.0.1 only where a partner depends on it.
The guides can be implemented one at a time, and CRD is the usual starting point because DTR depends on the questionnaire reference CRD returns and PAS usually depends on the QuestionnaireResponse DTR produces.
Yes. The PAS guide assumes an X12 278 sits behind the FHIR endpoint and defines how the Bundle maps to it. CMS's enforcement discretion means a plan that runs FHIR end to end won't be enforced against for skipping the 278, so either path works.
No. The Inferno kits check the parts that can be tested by a simulated EHR, such as discovery, extensions, and response shapes. Requirements like the 90% response time rule, log retention, and the accuracy of coverage answers have no test behind them, so conformance is a broader claim than a passing run.

What prior authorization is, why the process has been so slow, and what CMS-0057-F and HTI-4 require health plans to fix by January 2027.

Synthea generates brilliant synthetic patient data, but only in US Core. HiGHmed needed it in Germany's MII profiles. Here is how we rebuilt it. Fully open source.

Apple Health can pull your medical records straight from your hospital. Here's the FHIR stack behind it, SMART on FHIR, US Core, and the law that made it work.
No comments yet. Be the first to comment!