# ACH details, SEC codes & addenda

> Read achDetails and rail statuses on ACH transfers, and set custom statement descriptors, SEC codes, and TXP or remittance addenda when creating a transfer.

> AI agents: search and read all Moov docs with the docs MCP server at https://docs.moov.io/mcp (no API key). Setup: https://docs.moov.io/guides/developer-tools/mcp-ai/docs-mcp/index.md

Every ACH leg of a transfer has an `achDetails` object with its trace number, rail status, and any return or correction. You can also set fields in `achDetails` when you create a transfer to control the statement descriptor, SEC code, and addenda.

## Read ACH details on a transfer

You can obtain details about a transfer involving the ACH payment rail through the transfers `GET` [endpoint](/api/money-movement/transfers/get/index.md). If the source or destination uses an ACH payment method, the transfers details response will contain an `achDetails` object that contains useful information such as:

- `traceNumber`: tracking number (assigned by Moov) that can used by payment recipient to trace the payment with their external financial institution
- `return`: ACH return information per Nacha specification
  
  - `code`
  - `reason`
  - `description`
- `correction`: ACH notification of change information per Nacha specification
  
  - `code`
  - `reason`
  - `description`
- A transfer timestamp: Date-time information about transfer status changes
  
  - `initiatedOn`
  - `originatedOn`
  - `correctedOn`
  - `returnedOn`
  - `completedOn`

## ACH statuses

The `achDetails` also contains rail-specific status information:

| Status       | Description                                                                                                                         |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------|
| `initiated`  | The ACH transfer from the source into Moov's system has been created                                                                |
| `originated` | Payment instructions about the source transfer have been sent to Moov's originating depository financial institution (ODFI) partner |
| `corrected`  | The source transfer completed but a notification of change was received                                                             |
| `completed`  | Funds have been credited to the destination and are available for use                                                               |
| `returned`   | The payment was returned by Moov to the source financial institution                                                                |
| `canceled`   | The payment was successfully canceled                                                                                               |

## Customize ACH statement descriptors

You have the option to override the default Nacha file entries that appear on bank statements. To do this, set custom ACH statement descriptors when [creating a transfer](/api/money-movement/transfers/create/index.md). Use the following fields on the source, destination, or both, to provide more clarity or context for an individual transfer:

- `achDetails.companyEntryDescription`: Describe the purpose of the transaction
- `achDetails.originatingCompanyName`: Set the name how you'd like it to appear on the statement

Customizing these fields on the **source** will update the information on the bank statement where the debit occurs. Customizing these fields on the **destination** will update the information on the bank statement where the credit occurs.

For example, in a transfer where the source and destination are the same Moov account, your account's ACH company name would be used as the default originating company name unless a customization was set. The example below sets custom descriptors for both the source and destination.

**cURL**

```zsh
curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \
  -H "Authorization: Bearer {token}" \
  -H "x-idempotency-key: UUID" \
  -H "X-Wait-For: rail-response" \
  -H "x-moov-version: v2026.07.00" \
  --data-raw '{
    "amount": {
      "value": 100,
      "currency": "USD"
    },
    "destination": {
      "paymentMethodID": "string",
      "achDetails": {
        "companyEntryDescription" : "Gym dues",
        "originatingCompanyName" : "Whole Body Fit"
      }
    },
    "source": {
      "paymentMethodID": "string",
      "achDetails": {
        "companyEntryDescription" : "Gym dues",
        "originatingCompanyName" : "Whole Body Fit"
      }
    }
  }'
```

**Go SDK**

```go
mc, _ := moov.NewClient()

var accountID string

mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{
  Amount: moov.Amount{
    Currency: "USD",
    Value:    100, // $1.00
  },
  Destination: moov.CreateTransfer_Destination{
    PaymentMethodID: "string",
    AchDetails: &moov.CreateTransfer_AchDetailsBase{
      CompanyEntryDescription : "Gym dues",
      OriginatingCompanyName : "Whole Body Fit",
    },
  },
  Source: moov.CreateTransfer_Source{
    PaymentMethodID: "string",
    AchDetails: &moov.CreateTransfer_AchDetailsSource{
      CompanyEntryDescription : "Gym dues",
      OriginatingCompanyName : "Whole Body Fit",
    },
  },
})
```

## Set the SEC code

You have the option of specifying an SEC code in certain ACH transfer request scenarios. If none is provided, Moov will handle the SEC code on your behalf (`CCD` for business accounts and `PPD` for individual accounts).

| SEC code | Authorization type                | Description                                                                                                                                                                                                                                              | Supports addenda |
|----------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|
| `CCD`    | Corporate credit or debit         | An ACH debit *between two business accounts*, such as vendor payments or funding payroll.                                                                                                                                                                | Yes              |
| `PPD`    | Prearranged payment and deposit   | An ACH transaction involving *an individual account* to make or collect a payment.                                                                                                                                                                       | Yes              |
| `WEB`    | Internet initiated/mobile entries | Moov allows `WEB` transactions for debit entries *from an individual to a business account.* Authorization is obtained via the internet or a wireless network (not including oral authorization over a telephone).                                       | Yes              |
| `TEL`    | Telephone initiated entries       | An ACH debit *from an individual to a business account* with authorization obtained orally through a telephone, and recorded. See Nacha's [guidance](https://www.nacha.org/rules/meaningful-modernization) for use-cases and authorization requirements. | No               |

### Individual to business transactions

You have the option of specifying an SEC code on an ACH transaction that has an individual account as the source and a business account as the destination. The following SEC codes can be provided in **source.achDetails** when making a transfer `POST` [request](/api/money-movement/transfers/create/index.md): `WEB`, `TEL`, `PPD`. If no SEC code is provided, the SEC code will be set as `WEB`.

### Other transaction scenarios

If the source and destination of an ACH transaction are both business accounts, the SEC code will be set as `CCD`. If the source is a business account and the destination is an individual account, the SEC code will be set as `PPD`.

## Add addenda records

When you create a transfer, you can add supplemental payment information with an addenda record. Set an addenda in the `source.achDetails` and `destination.achDetails` object. Moov supports standard ACH and properly formatted TXP addenda.

Use cases for ACH addenda include:

- Tax payments (TXP addenda) required by the IRS and many state agencies
- B2B payments that include remittance or invoice references
- Specialized payments in healthcare, payroll, or government

The example below shows a transfer with a TXP addenda record. Addenda must use valid Nacha characters and be less than 80 characters in length.

```zsh
curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \
  -H "Authorization: Bearer {token}" \
  -H "x-idempotency-key: UUID" \
  -H "X-Wait-For: rail-response" \
  -H "x-moov-version: v2026.07.00" \
  -d '{
    "amount": {
      "value": 10000,
      "currency": "USD"
    },
    "source": {
      "paymentMethodID": "afaa9b4a-4fd7-4678-9fb7-d62e550fa13c",
      "achDetails": {
        "secCode": "CCD",
        "companyEntryDescription": "Tax payment",
        "originatingCompanyName": "The Body Shop Yoga",
        "addenda": [
          {
            "record": "TXP*123456789*94105*960301*1*10000*2*5000*3*15000"
          }
        ]
      }
    },
    "destination": {
      "paymentMethodID": "346039ed-2282-4936-bc30-1c3c396876aa",
      "achDetails": {
        "addenda": [
          {
            "record": "Invoice #INV-2025"
          }
        ]
      }
    },
    "description": "Federal tax payment"
  }'
```

### Data masking

ACH addenda, especially TXP records, may contain sensitive information such as SSNs or tax identifiers. For privacy and security reasons, Moov masks personally identifiable information and returns a safe addenda string in the response. If an addenda record has been masked, `isMasked` will be **true**, as shown below.

```json
{
  "achDetails": {
    "addenda": [ 
      {
        "isMasked": true,
        "record": "TXP*XXXXX6789*94105*960301*1*10000*2*5000*3*15000"
      }
    ]
  }
}
```

> **Note:** Moov does not validate the semantic correctness of TXP fields — only format, length, and eligibility. An addenda record added to a `TEL` SEC code is not allowed by Nacha and will be rejected.

