---
updatedAt: 2026-08-17T16:32:49.000Z
agentTools:
  projectIndex: https://docs.moderntreasury.com/payments/llms.txt
---

# Originate an ACH return

## Overview

Modern Treasury can support the origination of ACH returns. This may be helpful in cases where you are the receiving depository financial institution (RDFI) in a transaction and your bank account is credited or debited unexpectedly or incorrectly.

Because Modern Treasury originates the return on your behalf, the return is created against the incoming payment detail that represents the inbound entry, and the only fields you supply are `returnable_id`, `returnable_type`, `code`, and an optional `reason`. Amount, currency, and direction are derived from the incoming payment detail.

In most cases, there are rules that dictate how long you have to initiate a return, and which return codes you may use. The following codes are accepted, each limited to a specific direction of the original entry, account holder type, and window measured from the incoming payment detail's settlement date. Please not some return types require a [Written Statement of Unauthorized Debit](https://www.frbservices.org/resources/financial-services/ach/reference-guide/wsud.html) (WSUD) which must be collected before submitting the return.

| Code | Description                                | Original entry  | Account holder | Window           | WSUD Required |
| :--- | :----------------------------------------- | :-------------- | :------------- | :--------------- | ------------- |
| R07  | Authorization Revoked by Customer          | debit           | Individual     | 60 calendar days | Yes           |
| R08  | Payment Stopped                            | debit           | Any            | 2 banking days   |               |
| R10  | Customer Advises Unauthorized              | debit           | Individual     | 60 calendar days | Yes           |
| R11  | Entry Not in Accordance With Authorization | debit           | Individual     | 60 calendar days | Yes           |
| R23  | Credit Entry Refused by Receiver           | credit          | Any            | 2 banking days   |               |
| R24  | Duplicate Entry                            | debit or credit | Any            | 2 banking days   |               |
| R29  | Corporate Customer Advises Not Authorized  | debit           | Business       | 2 banking days   |               |

* A `debit` entry is one where funds were pulled out of your account; a `credit` entry is one where funds were pushed into it.
* The account holder is the legal entity associated with the account that received the entry. `R07`, `R10`, and `R11` may only be used on accounts held by an individual, and `R29` may only be used on accounts held by a business.
* Calendar-day windows count every day. Banking-day windows skip weekends and bank holidays.

If the code is not in the table above, does not match the direction of the original entry, does not match the account holder type, or its window has already closed, the request to create the return will fail with a `422` describing which condition was not met.

In this guide, we will walk through an example of originating an ACH return.

## 1. Identify an Incoming Payment Detail to be returned

Before you can initiate an ACH return, you need to have received an Incoming Payment Detail. You may have been notified about the Incoming Payment Detail via an `incoming_payment_detail.created`  [webhook](/platform/reference/incoming-payment-details).

You will need the ID of the Incoming Payment Detail to create the Return object. For the purposes of this guide, we will use the following sample Incoming Payment Detail. The Incoming Payment Detail ID is `0f8e3719-3dfd-4613-9bbf-c0333781b59f`.

```json Incoming Payment Detail object
{
  "id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
  "object": "incoming_payment_detail",
  "internal_account_id": "487b9a5c-6737-43ea-b11c-593f39226b92",
  "virtual_account_id": null,
  "virtual_account": null,
  "transaction_line_item_id": null,
  "transaction_id": null,
  "type": "ach",
  "data": {
    "role": "receiving",
    "message": "Transfer",
    "payment_type": "ach",
    "payment_subtype": "PPD",
    "receiving_party_name": "Test 4",
    "originating_party_name": "Test 4"
  },
  "amount": 10000,
  "currency": "USD",
  "direction": "credit",
  "status": "pending",
  "metadata": {},
  "as_of_date": "2020-10-17",
  "live_mode": true,
  "created_at": "2020-10-15T04:23:11Z",
  "updated_at": "2020-10-15T04:23:11Z"
}
```

## 2. Create the Return

Next, you can [create a Return](/platform/reference/create-return). The Return must adhere to the conditions noted in the overview section above.

```shell Creating a return
curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/returns \
  -H 'Content-Type: application/json' \
  -d '{
    "returnable_id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
    "returnable_type": "incoming_payment_detail",
    "code": "R23"
  }'
```

This API call will return a response that includes the return object.

```json Response
{
  "id": "08c251e1-4cba-4706-8faa-9c2df2682aa3",
  "object": "return",
  "returnable_id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
  "returnable_type": "incoming_payment_detail",
  "transaction_line_item_id": null,
  "transaction_id": null,
  "type": "ach",
  "role": "originating",
  "amount": 10000,
  "currency": "USD",
  "code": "R23",
  "reason": null,
  "live_mode": true,
  "status": "pending",
  "created_at": "2019-11-09T00:11:07Z",
  "updated_at": "2019-11-09T00:11:07Z"
}
```

When returning a debit as unauthorized (`R07`, `R10`, `R11`, or `R29`), you can optionally attach a written statement of unauthorized debit from the account holder via the return's **Documents** tab in the dashboard or the [Create Document](/platform/reference/create-document) endpoint using `document_type=written_statement_of_unauthorized_debit`, the only document type accepted for a return.

```shell Uploading a WSUD
curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/documents \
  -F documentable_type=return \
  -F documentable_id=08c251e1-4cba-4706-8faa-9c2df2682aa3 \
  -F document_type=written_statement_of_unauthorized_debit \
  -F file=@wsud.pdf
```

## 3. Monitor the Return

Once the return has been created, it will be transmitted to the bank prior to the next cutoff. You may monitor the return's status via the API or by subscribing to the [return webhooks](/platform/reference/returns). If the return succeeds, you will receive a `completed` webhook event. If it fails, you will receive a `failed` webhook event. The return's state will be reflected in the `status` attribute on the return object as well. The status of the incoming payment detail will only move to `returned` once the return succeeds at the bank; otherwise, it will remain in whatever state it was when the return was created.