Health-IT engineers & architects · 2026-07-02
Mapping HCR Action Codes to FHIR ClaimResponse: The Table Everyone Rebuilds
There is a table that every payer engineering team building for CMS-0057-F ends up writing. It has eight rows, one per X12 HCR action code, and columns for whatever FHIR and internal-status semantics the team needs. It gets written by the integration engineer wiring the FHIR-to-X12 bridge, then again by the UM platform team for their status model, then again by the analytics team computing approval rates, and once more in a Confluence page that drifts out of date within a quarter. Each copy disagrees somewhere — usually on partial approvals or pends — and the disagreement surfaces months later as a claims-matching dispute or a metrics discrepancy.
This article walks the mapping, flags where it is genuinely ambiguous, and argues for the boring fix: one owned artifact, referenced by everything.
Where the code lands on the FHIR side
Start with what the Da Vinci PAS implementation guide actually does with HCR01, because it is simpler than most people expect: it keeps it. The PAS ClaimResponse — the resource that leads every prior authorization response Bundle — carries a review-action extension on the item adjudication, and that extension's code element is bound, with a required binding, to the X12 value set for HCR01 (the value set URL points at the 005010X217 response's 2000F HCR01 element, X12 code list 306). The IG's own copyright note tells you the codes are X12's, licensed from X12.
The IG is equally direct about what the code means operationally: whether a response is considered pended, denied, or successful "depends on the review action code returned in the response," found in the ClaimResponse item adjudication's review-action code. In other words, PAS did not invent a new outcome vocabulary for prior authorization. The FHIR resource is the envelope; HCR01 is still the verdict.
This was a deliberate design choice. PAS assumes a translation era in which an intermediary converts FHIR Bundles to X12 278s and back (X12 itself is expected to publish the element-level mappings), so the IG avoids semantic transformations that a round-trip would mangle. For you, it means the interesting mapping is not X12-to-FHIR at all — that hop is nearly lossless by construction. The interesting mapping is code-to-meaning: what each HCR01 value implies for your canonical authorization status, your provider-facing display, your clocks, and your metrics.
The eight rows
- A1 — certified in total. The clean approval: everything requested is authorized as requested. Canonical status approved, clock stops, certification number / preAuthRef issued. The only row nobody argues about.
- A2 — certified, partial. Something was approved, but not everything requested. First ambiguity — see below.
- A3 — not certified. The UM denial. This is an adverse determination with all its regulatory freight: specific denial reasons (mandatory under CMS-0057-F regardless of channel), appeal rights, a row in your public denial metrics. Never conflate it with a transaction-level rejection.
- A4 — pended. No decision yet; frequently paired with a request for additional documentation. Second ambiguity — the lifecycle one.
- A6 — modified. The payer authorized something different from the request — a changed quantity, period, or level of care. Third ambiguity, jointly with A2.
- C — cancelled. The authorization or request was cancelled. Terminal, but not adverse: no appeal, no denial metric.
- CT — contact payer. The escape-to-a-human code. Map it to a distinct actionable status — never to pended, because nothing will arrive if the provider waits.
- NA — no action required. Often the "this service does not require prior authorization" answer. Decide explicitly whether your model treats it as approved-equivalent for claims matching; silence here creates downstream edits.
The three ambiguities that make the table hard
Partial versus modified (A2 versus A6). Both codes say "you got something other than what you asked for." The working distinction: A2 is subtractive — a subset of the request approved as submitted — while A6 is transformative — the payer changed the terms. But at the edges the distinction blurs (is six visits instead of twelve a partial certification or a modification of quantity?), and payer practice varies by companion guide. Your table cannot make payers consistent; what it can do is define your canonical semantics — for instance, both map to a partially-approved status that requires line-item comparison, with the original-versus-authorized delta computed and stored, not inferred later from claims. Whatever you choose, the choice must be written down once, because a bridge that maps A6 to "approved" while analytics maps it to "denied in part" will produce an approval-rate discrepancy someone eventually has to explain to a regulator.
Pended is a state, not an outcome. A4 is the one HCR01 value that is not terminal, and PAS builds real machinery around it: when a response pends, the IG requires implementers to support subscriptions so the submitter is notified when the response changes, alongside a claim inquiry operation for on-demand status checks — with the caveat that the inquiry response omits some content (such as the request for additional information), so it should not substitute for the subscription while awaiting final results. The IG also requires that initially-pended authorizations remain queryable for at least six months after the anticipated completion of the services. Your mapping table therefore needs more than a status word for A4: it needs the lifecycle contract — what state transitions are legal out of pended, which notification channel closes it, and what happens to the preAuthRef when a pend resolves. A 278-era UM system that models pended as just another final response will fight the FHIR rail's update semantics constantly.
Mixed outcomes within one response. The review action rides on item adjudication, and a multi-line request can come back A1 on one line, A4 on another, A3 on a third. Any rollup to a single request-level status (which your portal, your worklist, and probably your metrics all want) is an invention of yours, not of either standard. Define the precedence explicitly — a common choice is that any pended line keeps the request open, and any denied line makes it partially adverse — and put the precedence rule in the same owned artifact as the code table, because it is the same kind of decision.
One artifact, or five slow disagreements
The case for centralizing is not tidiness; it is that this table is a semantic contract enforced in four independent codebases. The bridge translates codes; the UM platform drives workflow; the metrics pipeline computes the approval, denial, and pend rates you now publish annually; the provider portal renders status text. If each holds its own copy, every ambiguity above is resolved four times by four people, and the copies drift precisely where the judgment calls live — A2, A6, NA, and the rollup rule.
The fix is unglamorous: one version-controlled mapping artifact (a code-reviewed enum-plus-table module, or a config the services load) that owns HCR01-to-canonical-status, the rollup precedence, the display strings, and the metrics classification per code. Changes go through review by someone who owns authorization semantics. Cross-rail lifecycle tests assert that a 278 response and its PAS translation land in the same canonical status — which is also the cheapest way to catch a bridge regression before a provider does. Teams that have consolidated on a single canonical status model report the same pattern: the table was a week of arguments to write once, and every copy of it avoided afterward is an incident that never happened.
The dual-rail era makes this table load-bearing. It deserves an owner, a version history, and exactly one address.
Verify extension structures, bindings, and pended-response requirements against the current HL7 Da Vinci PAS implementation guide (hl7.org/fhir/us/davinci-pas) and HCR01 code semantics against the X12 005010X217 TR3; both evolve.