> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spritz.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# ACH returns

> Understand, track, and reconcile returned ACH debits.

ACH is not a real-time, final network. An ACH debit can be **returned** after it
settles: the account holder's bank sends the money back, sometimes days or weeks later,
for reasons like insufficient funds or a claim that the debit wasn't authorized. Because
a [linked bank on-ramp](/guides/use-cases/linked-bank-onramp) delivers crypto against an
ACH pull, a return can mean funds you already moved need to be reconciled. This page
explains how returns work and how Spritz surfaces them.

## When returns arrive

Returns land within windows set by the ACH rules, which vary by reason:

* **Administrative** returns (wrong or closed account, invalid number) usually arrive
  within about two banking days.
* **Unauthorized** returns (the account holder disputes the debit) can arrive up to 60
  calendar days after settlement.

Spritz groups returns into three buckets, `unauthorized`, `administrative`, and
`other`, so you can treat them differently.

## How Spritz surfaces a return

When a debit is returned:

* The deposit's `status` and `debitStatus` become `returned`, and the deposit carries a
  `returnCode` and `returnReason`.
* The `achDebitReturn.created` [webhook](/guides/webhooks) fires, followed by
  `achDebitReturn.updated` as details change.

You can also list returns directly:

```bash theme={null}
curl "https://platform.spritz.finance/v1/integrator/ach-debit/returns?returnBucket=unauthorized" \
  # plus your integrator signing headers (see Authentication)
```

Each return record ties the return back to its deposit and quantifies your exposure:

| Field                                         | Meaning                                                                                                       |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `depositId`, `onRampId`, `userId`, `sourceId` | What and who the return relates to                                                                            |
| `returnCode`, `returnReason`                  | The ACH return reason (see below)                                                                             |
| `reportingBucket`                             | `unauthorized`, `administrative`, or `other`                                                                  |
| `occurredAt`                                  | When the return was received                                                                                  |
| `cryptoStateAtReturn`                         | Whether the crypto had already left: `not_released`, `in_flight`, `partially_confirmed`, or `fully_confirmed` |
| `lossAmountUsd`, `atRiskAmountUsd`            | Realized loss and still-at-risk amount                                                                        |

`cryptoStateAtReturn` is the key exposure signal: a return before the crypto is released
costs you nothing, while a return after `fully_confirmed` delivery is a realized loss.

## Common return codes

ACH return codes follow the NACHA standard (`R01`, `R02`, and so on). The ones you'll
see most:

| Code  | Reason                                     |
| ----- | ------------------------------------------ |
| `R01` | Insufficient funds                         |
| `R02` | Account closed                             |
| `R03` | No account or unable to locate account     |
| `R04` | Invalid account number                     |
| `R07` | Authorization revoked by the customer      |
| `R08` | Payment stopped                            |
| `R10` | Customer advises the debit is unauthorized |
| `R16` | Account frozen                             |
| `R20` | Non-transaction account                    |
| `R29` | Corporate customer advises not authorized  |

This is a subset. The full set of codes is defined by NACHA, and `returnReason` carries
the human-readable text for whatever code applies.

## Keeping return rates low

The ACH network holds originators to return-rate thresholds (for example, a low cap on
unauthorized returns), and exceeding them can put ACH access at risk. To protect that,
Spritz runs risk checks before every debit and may block a deposit, returning a `409` at
create time **before any funds move**, rather than risk a costly return. Only debit
accounts your user has clearly authorized, and reconcile returns promptly.

## Reconciling

<Steps>
  <Step title="Listen for the webhook">
    Subscribe to `achDebitReturn.created` and `achDebitReturn.updated` so you learn about
    returns as they happen.
  </Step>

  <Step title="Assess exposure">
    Use `cryptoStateAtReturn` and `lossAmountUsd` to decide whether the return is a real
    loss or was caught before delivery.
  </Step>

  <Step title="Act">
    Recover from the user where appropriate, and factor repeated returns into whether you
    continue to offer ACH debit to that user.
  </Step>
</Steps>
