Handling Reject Code 75: Prior Authorization Required

Reject code 75 is the one coverage reject that is not a dead end — it tells the pharmacy the drug is coverable, but only behind a prior-authorization gate that has not yet been satisfied. Where 70 Product/Service Not Covered closes the door, 75 opens a workflow: it signals that the plan will pay for this GPI once a PA is approved, or once the member completes a step-therapy sequence, so the pharmacist knows to initiate prior-authorization intake rather than send the member away. Emitting 75 correctly is therefore a routing decision as much as a coverage decision — the code has to fire only when there is a genuine PA path forward, and it has to carry the claim into the Prior Authorization Routing Automation pipeline. This guide, part of the NCPDP Reject Code Reference, specifies the trigger conditions and the Python handler that emits 75 and hands off to PA.

The Exact Decision

75 fires when a claim clears eligibility and formulary coverage but hits a gate the member has not passed. There are two distinct triggers behind the single code. The first is a PA-required drug: the GPI is flagged in the formulary as requiring prior authorization outright — common for specialty agents, high-cost biologics, and drugs with narrow approved indications. The second is unsatisfied step therapy: the GPI is coverable without a standing PA, but the plan requires the member to have tried and failed one or more preferred agents first, and the Step Therapy & Prior Auth Trigger Rules evaluation found the sequence incomplete. Both produce 75, but the handler tags which trigger fired so the PA workflow knows whether it is opening a clinical-review case or a step-therapy exception.

The disambiguation that matters most is 75 versus 70: the difference is whether a PA path exists at all. The table encodes the boundaries.

Symptom on the claim Correct code Why not 75
GPI requires prior authorization, none on file 75 Prior Authorization Required This is the canonical 75 case
GPI coverable but step therapy incomplete 75 Prior Authorization Required PA/exception path exists; sequence unmet
GPI is excluded from the formulary 70 Product/Service Not Covered No PA path exists; the door is closed
GPI covered, no gate, quantity too high 76 Plan Limitations Exceeded Coverable now; only the amount is wrong
An approved PA is already on file for this member+GPI (pass) The gate is satisfied; do not re-reject
A DUR safety edit hard-stops the claim 88 DUR Reject Error Clinical safety, not a PA gate

The operating rule the handler encodes: 75 means “coverable, but gated, and a path forward exists.” If no path exists it is 70; if the gate is already satisfied by an approved PA the claim passes; if the block is a hard clinical-safety edit it is 88, not 75.

Step-by-Step Implementation

The handler runs after coverage confirms the GPI is on formulary. It checks for an existing approved PA, then evaluates the PA-required flag and the step-therapy verdict, and on a gate miss it emits 75 and routes into intake.

1. Check for an existing approved PA first. A member+GPI with an active, in-window PA on file has already cleared the gate — passing this check must short-circuit before any 75 is raised, or the engine re-rejects an already-authorized fill.

2. Evaluate the PA-required flag from the versioned formulary snapshot. If the GPI is flagged PA-required and no approval exists, that is a 75 on the pa_required trigger.

3. Consult the step-therapy verdict. If step therapy is required and the sequence is unmet, that is a 75 on the step_therapy trigger. A satisfied or not-applicable sequence does not raise 75.

4. Build the 511-FB response and route to intake. Set 501-F1 Header Response Status to R, attach 511-FB = "75", and emit a routing envelope carrying the tokenized reference and the trigger tag into Prior Authorization Routing Automation.

5. Log the outcome PHI-safely. Only the tokenized 402-D2 reference, the 511-FB code, and the trigger reach the logger.

python
import json
import logging
import enum
from typing import Optional
from pydantic import BaseModel, ConfigDict

logging.basicConfig(format="%(message)s", level=logging.INFO)
logger = logging.getLogger("reject_75")


class PATrigger(str, enum.Enum):
    NONE = "none"
    PA_REQUIRED = "pa_required"
    STEP_THERAPY = "step_therapy"


class StepVerdict(str, enum.Enum):
    NOT_APPLICABLE = "not_applicable"
    SATISFIED = "satisfied"
    UNMET = "unmet"


class Reject75Input(BaseModel):
    model_config = ConfigDict(frozen=True, extra="forbid")
    gpi: str                       # resolved GPI (coverage already confirmed)
    claim_ref: str                 # tokenized 402-D2, non-PHI
    pa_required: bool              # PA-required flag from formulary snapshot
    approved_pa_on_file: bool      # active, in-window PA for member+GPI
    step_verdict: StepVerdict      # from step-therapy evaluation


class Reject75Result(BaseModel):
    status: str                    # "PASS" or "REJECT"
    reject_511fb: Optional[str] = None
    trigger: PATrigger = PATrigger.NONE
    route: Optional[str] = None


def handle_reject_75(inp: Reject75Input) -> Reject75Result:
    # 1. An approved PA already clears the gate -> never re-reject.
    if inp.approved_pa_on_file:
        result = Reject75Result(status="PASS")
    # 2. PA-required drug, no approval on file.
    elif inp.pa_required:
        result = Reject75Result(
            status="REJECT", reject_511fb="75",       # 501-F1 = R downstream
            trigger=PATrigger.PA_REQUIRED, route="pa_intake",
        )
    # 3. Step therapy required but the sequence is unmet.
    elif inp.step_verdict is StepVerdict.UNMET:
        result = Reject75Result(
            status="REJECT", reject_511fb="75",
            trigger=PATrigger.STEP_THERAPY, route="pa_intake",
        )
    else:
        result = Reject75Result(status="PASS")

    # PHI GUARDRAIL: tokenized ref + 511-FB + trigger only. Never 302-C2
    # Cardholder ID, 310-CA Patient Name, prescriber PHI, or raw claim bytes.
    logger.info(json.dumps({
        "event": "reject_75_eval",
        "claim_ref": inp.claim_ref,
        "reject_511fb": result.reject_511fb,
        "trigger": result.trigger.value,
        "route": result.route,
    }))
    return result

The handler is a pure function of its input contract, so it is thread-safe and replayable against the formulary snapshot and step verdict that were live at fill time. The approved_pa_on_file short-circuit is the single most important line: a race where an approval lands between two retries must resolve to a pass, not a stale 75, which is exactly the concern addressed in Resolving PA Pend Race Conditions.

Reject 75 prior-authorization gate flow After coverage confirms the GPI is on formulary, the handler first checks for an approved prior authorization on file; if present the claim passes. Otherwise, a PA-required flag rejects 75 with a pa_required trigger, and an unmet step-therapy verdict rejects 75 with a step_therapy trigger. Both rejects route into prior-authorization intake. A satisfied gate passes to the next rule. Coverage confirmed Approved PA on file? PA-required or step unmet? Pass → next rule gate satisfied Reject 75 · PA required route: PA intake Pass → next rule no gate applies yes no yes no

Figure: An approved PA short-circuits to a pass; a PA-required flag or unmet step therapy yields 75 and routes into intake.

Verification and Testing Pattern

Test each trigger and, critically, the approved-PA short-circuit that must never re-reject an authorized fill.

python
import pytest


def _inp(**kw):
    base = dict(gpi="6410001000XXYY", claim_ref="tok-xyz",
               pa_required=False, approved_pa_on_file=False,
               step_verdict=StepVerdict.NOT_APPLICABLE)
    base.update(kw)
    return Reject75Input(**base)


def test_pa_required_rejects_75():
    r = handle_reject_75(_inp(pa_required=True))
    assert r.reject_511fb == "75" and r.trigger is PATrigger.PA_REQUIRED
    assert r.route == "pa_intake"


def test_unmet_step_therapy_rejects_75():
    r = handle_reject_75(_inp(step_verdict=StepVerdict.UNMET))
    assert r.reject_511fb == "75" and r.trigger is PATrigger.STEP_THERAPY


def test_approved_pa_passes_even_if_flagged():
    # The short-circuit must win over the PA-required flag.
    r = handle_reject_75(_inp(pa_required=True, approved_pa_on_file=True))
    assert r.status == "PASS" and r.reject_511fb is None


def test_satisfied_step_passes():
    r = handle_reject_75(_inp(step_verdict=StepVerdict.SATISFIED))
    assert r.status == "PASS"

test_approved_pa_passes_even_if_flagged is the load-bearing case: it pins that an on-file approval overrides the PA-required flag, the exact behavior that prevents a re-adjudicated claim from bouncing a member who already has authorization.

Gotchas and PHI Guardrails

  • The approved-PA check must come first. Ordering the PA-required flag before the on-file check re-rejects authorized members on every retry. Evaluate approved_pa_on_file before anything else.
  • 75 requires a real path forward. Never emit 75 for a formulary-excluded drug just because it looks high-cost — an exclusion is 70, and sending a 70 case into PA intake floods the queue with claims that can never be approved.
  • Step-therapy 75 versus a hard clinical stop. An unmet step sequence is a 75 (exception path exists); a drug-drug interaction or dose-safety hard-stop is 88 DUR Reject Error, which has no PA remedy. Keep them separate.
  • Tag the trigger. The PA workflow behaves differently for a standing PA-required drug versus a step-therapy exception; carrying the PATrigger tag lets intake open the right case type instead of guessing.
  • Watch the pend race. An approval landing mid-adjudication can produce a spurious 75; resolve on the tokenized reference as an idempotency key and reconcile via Resolving PA Pend Race Conditions.
  • Log only tokens and codes. The routing envelope and every log line carry the tokenized 402-D2 reference, the 511-FB code, and the trigger — never 302-C2 Cardholder ID, 310-CA Patient Name, 411-DB prescriber identity, or raw claim bytes.

For the standard field and reject-code definitions this handler relies on, consult the official NCPDP Standards documentation.

← Back to NCPDP Reject Code Reference