A credit denial that fails to explain itself is a compliance event, not just a customer-service problem. Under the Equal Credit Opportunity Act and Regulation B, a creditor that takes adverse action has to give the applicant a statement of specific reasons that indicates the principal reason or reasons for the decision. The reasons have to be accurate. They have to reflect what the system actually weighed.
This is where the data substrate and the model meet the consumer. Everything earlier in this course (lineage, consent, proxy testing, less-discriminatory alternatives) feeds into whether the model is defensible. The adverse-action notice is where the model has to account for itself in writing, to the person it just declined. If your reasons do not trace back to the model's actual behavior on that application, the rest of the pipeline does not save you.
What Reg B actually requires
Reg B (12 CFR 1002.9) says the statement of reasons must be specific and indicate the principal reasons for the adverse action. Two stock answers are explicitly insufficient: that the decision was based on the creditor's internal standards or policies, and that the applicant failed to achieve a qualifying score on the creditor's credit scoring system. Neither tells the applicant anything actionable.
The official commentary draws a hard line for scored systems. When a creditor bases the decision on a credit scoring system, the disclosed reasons must relate only to factors actually scored in the system, and no factor that was a principal reason may be left out. So the bar is two-sided. You cannot list a factor the model did not use, and you cannot omit a factor that drove the decision.
The commentary also notes that the regulation does not fix a required number of reasons, but that disclosing more than four is not likely to help the applicant. In practice most teams disclose up to four principal reasons.
The sample-form checklist is not a safe harbor
The CFPB's sample forms in Reg B include a checklist of common reasons plus an open "other" field. Circular 2023-03 made the point bluntly: a creditor using AI or complex models may not rely on that checklist if the listed reasons do not specifically and accurately indicate the principal reasons. If the real driver is not on the list, you modify the form or check "other" and write the actual reason. Ticking the nearest box is not compliance.
"The model is too complex" is not a defense
CFPB Circular 2022-03 closed the most common excuse. Creditors using complex algorithms, including machine learning, must still disclose the specific principal reasons for an adverse action. A creditor's own lack of understanding of its methods is not a cognizable defense. If the model is too opaque to explain, the answer is not a vaguer notice. The answer is a model you can explain.
The circular gives a concrete example of insufficient specificity. If a complex algorithm denies an application because of the applicant's chosen profession, a notice saying "insufficient projected income" or "income insufficient for amount of credit requested" would likely not suffice, because it does not tell the applicant what actually happened. The notice has to name the real driver, even when the real driver is something the applicant would never guess.
That last point matters for any model trained on data outside the application and credit file. Circular 2023-03 warns that consumers may not anticipate that data not intuitively tied to their finances became a principal reason. The more exotic your features, the more precise your reasons have to be.
Generating reasons from the model, not around it
The technical job is to turn a single applicant's prediction into a short, accurate, plain-language list of the factors that pushed the decision toward denial. The standard tooling is per-applicant feature attribution: compute how much each input moved this prediction away from an approval baseline, rank the inputs that pushed toward denial, and map the top few to a controlled vocabulary of reason codes.
Three engineering rules keep this honest.
First, attribute against a defensible baseline. SHAP and similar methods explain a prediction relative to a reference point. If your baseline is an "approved applicant" reference, the top negative contributors are the factors that separated this applicant from approval, which is exactly the population Reg B cares about. Document the baseline choice and keep it stable across the portfolio.
Second, explain the model that made the decision. Running an attribution method on a separate surrogate model gives you a plausible story, not the actual driver. If the scoring model and the explanation model can diverge, you can disclose a reason that had nothing to do with the decision. Generate reasons from the same artifact that produced the score, at the same model version.
Third, group correlated features before you rank. If trade-line count, utilization, and recent inquiries each contribute a little and all describe revolving-credit behavior, a raw top-four list can bury the real theme under near-duplicates. Sum attributions within a signal group, then map the group to one reason code. This both improves accuracy and avoids spending all four slots on one underlying factor.
A worked example
An applicant is declined by a gradient-boosted model. Per-applicant attributions, computed against an approved-population baseline and grouped by signal, rank the denial drivers as: high revolving utilization, short length of credit history, a recent delinquency, and high requested-amount-to-income ratio.
The notice should name those four, in the applicant's language: "Proportion of balances to credit limits is too high," "Length of credit history is too short," "Recent serious delinquency," and "Requested loan amount is high relative to income." Each one is a factor the model actually scored, each one is a principal driver for this applicant, and none is a generic "did not meet our standards."
Now the failure mode. Suppose the largest real driver was a cash-flow feature derived from bank-transaction data, and the team mapped it to "insufficient income" off the sample checklist because there was no closer box. That notice is wrong twice: it names a factor the model did not use as stated, and it omits the factor that actually drove the denial. Per Circular 2022-03's profession example, that is the kind of mismatch the CFPB calls out. The fix is to add a reason code that describes the cash-flow signal in plain terms and disclose it.
Make the mapping auditable
The reason a notice is defensible is that you can reconstruct it. For every adverse-action decision, store the model version, the exact feature inputs, the attribution decomposition, the grouping logic, the ranked drivers, and the reason codes that were sent. That record lets you prove, applicant by applicant, that the disclosed reasons match what the model did. It also lets you spot drift, where a reason code starts appearing far more often than the underlying feature distribution would justify, which usually means the mapping or the model has moved.
Keep the reason-code vocabulary versioned and reviewed. When a feature is added, removed, or re-weighted, the set of reasons it can produce changes, and the mapping has to change with it. A stale reason-code table is how a model that improved last quarter ends up sending last year's explanations.
Takeaway
The adverse-action notice is the model's testimony about a single decision, and ECOA holds you to its accuracy. Generate reasons from the deciding model against a stable baseline, group correlated signals, disclose the genuine principal drivers in the applicant's language, and keep a per-decision record that proves the match. Complexity buys you no leniency here. If you cannot say why the model said no, you are not allowed to have it say no.