WhyDunit · UPI AutoPay revenue recovery

Know why the debit failed.
Then fix only that.

WhyDunit attributes every failed UPI AutoPay debit to one of four causes — execution window, notification failure, balance shortfall, or cancellation — and executes a bounded recovery action matched to that cause. When the cause is cancellation, it stops instead of spending.

A third of what merchants write off as churn was never the customer. Retrying those on a timer recovers a third of the money and burns the rest on people who already left.

At risk
₹20.87L
Recovered
63.1%
Naive retry
33.3%

01 — The evidence

The decline code tells you nothing.

mdt_00004FAILED
Amount₹499
BankSBI
Attempted22 May 2026 · 11:07 IST
Decline codeZM
Notice deliveredconfirmed
Customer balancenot observable

ZM is returned for several different reasons. In this corpus no decline code is a reliable proxy for a cause — the most predictive one still misclassifies roughly a fifth of the time.

The bank told you it failed. It did not tell you why, and the one fact that would settle it — the customer’s balance — is not something a merchant can see.

02 — Four suspects

Each one fails differently.

Every cause moves with something and is invariant to the rest. That signature separates them — not the code the bank sent.

C1

Execution window

Debited inside NPCI's 10:00–13:00 block. Moves with the hour; invariant to customer, bank and amount.

—
C2

Notification failure

Pre-debit notice not delivered 24h ahead. Moves with the bank and with outage bursts.

—
C3

Balance shortfall

No funds at the moment of debit. Moves with the customer and the day of the month.

—
C4

Cancellation

The customer has stopped paying. Moves with nothing at all. Nothing fixes it.

—

03 — Why a timer can never fix it

T+24h keeps the hour.

A fixed-interval retry advances the date and preserves the time of day. Against a rule written in hours, every retry lands on the same spoke.

00061218

Naive retry · T+24h, T+72h, T+168h

0.0%

of execution-window failures recovered. Not fewer — none.

WhyDunit · same day, 14:07

0.0%

attribution accuracy on this class. mdt_00004 recovered on the first retry, 99.9% confidence.

04 — One customer, one year

Watch it recover, hesitate, and then give up.

These are the agent’s own audit rows for a single mandate, replayed as you scroll. Nothing here is staged — every line is read from the log the agent wrote while running.

mdt_00060KOTAK · ₹999 monthly · 2026
  1. FEB02:52C3 Balance shortfallrescheduledrecovered
  2. MAR14:03C1 Execution windowrescheduledrecovered
  3. APR—C3 Balance shortfallsent to a humanhuman review
  4. JUN13:09C3 Balance shortfallrescheduledrecovered
  5. JUL21:02C3 Balance shortfallrescheduledrecovered
  6. AUG20:36C3 Balance shortfallrescheduledfailed
  7. AUG20:36C3 Balance shortfall · retry 2/3rescheduledfailed
  8. AUG14:00C3 Balance shortfall · retry 3/3rescheduledfailed
  9. SEP—C4 Cancellationstoppedno further retries
Recovered on this mandate
₹0
Scroll to replay the year.

Four cycles recovered. One held back because confidence fell to 0.54. Three retries in August that went nowhere. Then, in September, P(cancelled) crossed 0.95 and it stopped — the one decision a fixed-interval retry can never make, because a timer has no opinion about whether the customer is still there.

05 — At scale

3,116 failures, one seeded run.

Every policy gets the same three retries over the same failures. Deltas are paired bootstrap, 1,000 resamples clustered by mandate.

Do nothing0.0%
Naive retry33.3%
Window-aware retry49.9%
Expert rule62.9%
WhyDunit63.1%
Oracle ceiling64.8%

+29.8pp against naive retry [24.8, 35.5], at 1.79 retries per failure instead of 2.67. Attribution: 88.4% auto-classified at macro-F1 0.881 [0.857, 0.901].

06 — What it cannot do

The tie is the honest headline.

Ties the rule
Against a hand-written four-line expert rule the difference on rupees is +0.1pp [-0.6, 0.8] — it straddles zero. The rule stays the production retry policy. The model earns its place in attribution, where it leads by +0.181 macro-F1.
Silent churn
Recall on cancellations with no webhook is 0.556 here and 0.000 at a 90-day horizon. Invariance needs repeated attempts before it can be seen at all.
Simulated corpus
A labelled corpus of UPI AutoPay failures with known ground truth does not exist outside a PSP. The simulator generates world state; labels are emergent, never assigned.
Adapter unproven
The Razorpay adapter is built against test mode and unit-tested, and has never run against live credentials. Only one of the four causes is inducible in test mode.

Every figure here comes from one seeded run — seed 20260903, 270-day horizon. npm run verify regenerates the world and re-hashes ten artifacts against a committed manifest, on any CPU architecture.

Open the dashboard →Read the source