ACH Return Codes Explained: R01–R85 and How to Handle Them in Production
ACH Return Codes Explained: R01–R85 and How to Handle Them in Production
When an ACH payment fails, your API doesn't just return a generic error. The National Automated Clearing House Association (Nacha) defines 85 specific return codes—each one telling you exactly why a debit or credit entry was rejected. Understanding these codes is essential for building reliable payout systems that recover gracefully instead of leaving money in limbo.
Why ACH Return Codes Matter
ACH operates on a two-day settlement cycle. A payment you initiate today may return tomorrow or the day after. When it does, your system needs to know whether the issue is temporary (retry-able), permanent (route elsewhere), or requires customer action (dunning).
The Nacha return code set spans R01 through R85. Each code is a three-character string that maps to a specific rejection reason. Ignoring the distinction between, say, R01 (insufficient funds) and R03 (no account) means you'll retry payments that will never succeed, or fail to retry ones that might.
Common Return Codes and What They Mean
| Code | Reason | Retry? | Action |
|---|---|---|---|
| R01 | Insufficient funds | Yes | Retry after 3–5 days or dunning |
| R02 | Account closed | No | Update customer; route to alternate |
| R03 | No account / invalid account | No | Verify account details with customer |
| R04 | Invalid account type | No | Confirm account is checking/savings |
| R05 | Account frozen | No | Customer must unfreeze; escalate |
| R07 | Authorization revoked | No | Reauthorize or use new account |
| R10 | Customer advises not authorized | No | Dispute or reauthorize |
| R14 | Representative payee deceased | No | Escalate; may require legal action |
| R16 | Account subject to legal process | No | Escalate to compliance |
| R20 | Non-transaction account | No | Route to alternate payment method |
| R29 | Corporate customer advises not authorized | No | Reauthorize at corporate level |
Handling R01: Insufficient Funds
R01 is the most common return. A customer's account balance dropped between authorization and settlement. Your response:
- Log the return with timestamp and original entry ID.
- Retry once after 3–5 business days (funds may have been deposited).
- If retry fails, trigger dunning: email the customer, offer to retry, or suggest a lower amount.
- After 2–3 failed attempts, mark the account as high-risk and require manual approval for future payouts.
def handle_ach_return(return_code, payout_id, receiver_account):
"""
Decode ACH return and decide next action.
"""
if return_code == "R01":
# Insufficient funds: retry-able
schedule_retry(payout_id, delay_days=3)
send_dunning_email(receiver_account)
return {"status": "retry_scheduled", "next_attempt": "+3 days"}
elif return_code in ["R02", "R03", "R04"]:
# Account closed or invalid: not retry-able
flag_account_invalid(receiver_account)
notify_customer_verify_account(receiver_account)
return {"status": "account_invalid", "action": "manual_review"}
elif return_code == "R10":
# Customer advises not authorized
flag_dispute(payout_id, return_code)
escalate_to_compliance(payout_id)
return {"status": "dispute_flagged"}
else:
# Other codes: escalate
escalate_to_support(payout_id, return_code)
return {"status": "escalated", "code": return_code}
Non-Retry Codes Require Alternate Rails
Codes like R02 (account closed), R03 (no account), and R05 (account frozen) signal that ACH will never work for that receiver. Your payout system should:
- Mark the account as ACH-ineligible.
- Offer alternatives: Visa Direct, RTP, check, or wire.
- Log the decision for audit and reconciliation.
Reconciliation and Timing
ACH returns arrive in batches, typically 1–2 business days after the settlement date. Your reconciliation job must:
- Parse return files (Nacha format or via your processor's API).
- Match return entries to original payout records by trace number.
- Decode the return code and trigger the appropriate handler.
- Update payout status (e.g.,
status = "returned",return_code = "R01").
Most processors provide a webhook or API endpoint for return notifications. Hook into it
Decoding ACH return codes programmatically? The ACH Return Codes API returns the full Nacha R01–R85 set with plain-language descriptions and handling guidance.
Top comments (0)