ACH Return Codes Explained: R01–R85 and How to Handle Them in Production

작성자

카테고리:

← 피드로
DEV Community · Payout Rail · 2026-09-29 개발(SW)

Payout Rail

ACH Return Codes Explained: R01–R85 and How to Handle Them in Production

Why ACH Return Codes Matter

When a payout fails, you don’t get a generic “error.” You get an ACH return code—a two-character alphanumeric that tells you exactly why the transfer bounced. Understanding these codes is the difference between a retry loop that wastes money and a dunning strategy that recovers the transaction.

The National Automated Clearing House Association (NACHA) publishes the official return code set. There are 85 defined codes (R01 through R85), each with specific remediation paths. A developer who can decode these codes programmatically can automate recovery, flag fraud, and route payouts to alternate rails without manual intervention.

Common Return Codes and What They Mean

R01: Insufficient Funds

The account exists and is valid, but the balance is too low to cover the debit. This is recoverable—the recipient may have funds tomorrow.

Developer action: Queue a retry after 2–3 business days. Log the original transaction ID and amount so you can reconcile when the retry succeeds.

{
  "return_code": "R01",
  "recipient_account": "123456789",
  "amount_cents": 50000,
  "return_reason": "Insufficient funds",
  "recommended_action": "retry_in_3_days",
  "retry_count": 1
}

Enter fullscreen mode Exit fullscreen mode

R03: No Account / Unable to Locate Account

The routing number and account number don’t match any active account at that bank. This is not recoverable via ACH retry.

Developer action: Flag for manual review. Contact the recipient to verify account details. Consider routing the next attempt via RTP (Real-Time Payments) if available, which has better account validation upstream.

R10: Customer Advises Not Authorized

The recipient’s bank received a dispute claiming the debit was unauthorized. This is a fraud signal.

Developer action: Stop all further payouts to that account. Log the incident and require the recipient to re-authorize via your dashboard before attempting another payout.

R29: Corporate Customer Advises Not Authorized

Similar to R10, but initiated by a business account. Same remediation: halt and require re-authorization.

R07: Authorization Revoked by Customer

The recipient previously authorized ACH debits but has since revoked consent. This is terminal for ACH.

Developer action: Update your records to mark that account as “ACH revoked.” Offer the recipient alternative payout methods (wire, card, RTP).

Building Return-Code-Aware Logic

Here’s a pattern for handling returns programmatically:

const ACH_RETURN_HANDLERS = {
  'R01': { action: 'retry', delay_days: 3, max_retries: 2 },
  'R03': { action: 'manual_review', notify_recipient: true },
  'R07': { action: 'halt', require_reauth: true },
  'R10': { action: 'fraud_hold', notify_compliance: true },
  'R29': { action: 'fraud_hold', notify_compliance: true },
  'R14': { action: 'manual_review', reason: 'Representative payee deceased' },
};

function handleACHReturn(returnCode, payoutRecord) {
  const handler = ACH_RETURN_HANDLERS[returnCode];

  if (!handler) {
    console.warn(`Unknown return code: ${returnCode}`);
    return { action: 'manual_review' };
  }

  if (handler.action === 'retry') {
    scheduleRetry(payoutRecord.id, handler.delay_days, handler.max_retries);
  } else if (handler.action === 'fraud_hold') {
    flagAccount(payoutRecord.recipient_id, 'fraud_suspected');
    notifyCompliance(returnCode, payoutRecord);
  } else if (handler.action === 'manual_review') {
    escalateToSupport(payoutRecord, returnCode);
  }

  return handler;
}

Enter fullscreen mode Exit fullscreen mode

Return Timing and Reconciliation

Returns arrive in two windows:

  • Standard returns: Posted within 2 business days of the payout settlement date.
  • Late returns: Posted up to 60 days after settlement (rare, but they happen).

Your reconciliation logic must account for both. A payout marked “settled” is not final until the return window closes.

When to Abandon ACH

If an account returns R03 or R07, or if it hits R01 three times in a row, consider offering RTP (instant, 24/7) or Visa Direct (card-based, if the recipient has a card on file). These rails have different cost structures and settlement speeds, but they bypass ACH’s batch-window constraints.

Takeaway

ACH return codes are not noise—they’re actionable signals. Decode them, automate your response, and your payout system will recover more

Decoding ACH return codes programmatically? The ACH Return Codes API returns the full Nacha R01–R85 set with plain-language descriptions and handling guidance.

원문에서 계속 ↗