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

# The ACH Object

> Field-level reference for the ACH object, including core balance and core transaction links, record details, counterparty, returns, reversal, rejection, correction, list filters, and how it maps from the v1 ACH API.

Lead creates an ACH object for every entry your program sends and every entry it receives. You create outgoing entries with `POST /v2/ach` and read them with `GET /v2/ach` and `GET /v2/ach/{ach_id}`. Returns, dishonored returns, contested returns, reversals, rejections, and corrections are recorded on the same object. `POST /v2/ach` requires an `Idempotency-Key` header. See [Idempotency](https://docs.lead.bank/api-reference/using-the-api/idempotency-v2.md).

This example is an incoming debit. A gym pulled \$50 from an Acme customer's account number, and the entry posted. The customer told Acme the debit wasn't authorized, so Acme returned it with `POST /v2/ach/{ach_id}/return` and return code R10. The return posted, and the entry is now `returned`.

```json theme={null}
{
  "id": "ach_3KrLe9Wc4OlYa7nZsU5xF2bR8t",
  "account_number_id": "account_number_2fTZ4St5HSJnxzv7jdevxQnev3U",
  "core_balance_id": "core_balance_2xYw9Kn3Jp7QuS2lY5mAbC0dE4f",
  "core_transaction_id": "core_transaction_2pR8Jt1Wc4OlYa7nZsU5xF2b",
  "created_at": "2026-10-08T14:11:05Z",
  "updated_at": "2026-10-10T12:30:44Z",
  "status": "returned",
  "amount": 5000,
  "currency_code": "USD",
  "direction": "incoming",
  "delivery_type": null,
  "transaction_type": "debit",
  "sec_code": "PPD",
  "statement_descriptor": "PEAK FITNESS",
  "record_details": {
    "transaction_code": "checking_debit",
    "company_name": "Peak Fitness LLC",
    "company_id": "9876543210",
    "company_discretionary_data": null,
    "effective_date": null,
    "settlement_date": "2026-10-09",
    "individual_id": "MBR-77102",
    "receiver_name": "Jordan Smith",
    "descriptive_date": null,
    "additional_information": null,
    "trace_number": "123456780000131"
  },
  "counterparty": {
    "name": "Peak Fitness LLC",
    "account_number": null,
    "routing_number": "123456789",
    "account_type": null
  },
  "returns": [
    {
      "type": "return",
      "status": "posted",
      "return_code": "R10",
      "reason": "Customer advises not authorized",
      "details": null,
      "trace_number": "123456780000512",
      "core_transaction_id": "core_transaction_2pS9Ku2Xd5PmZb8oAtV6yG3c"
    }
  ],
  "reversal": null,
  "rejection": null,
  "correction": null,
  "iat_details": null,
  "metadata": {}
}
```

The core balance has two core transactions: the debit from when the entry posted, linked at the top level, and the credit from when the return posted, linked on the `returns[]` entry.

## Fields

The table lists each field on the object.

| Field | Type | Description |
| - | - | - |
| `id` | string | Unique identifier, prefixed `ach_`. |
| `account_number_id` | string | The account number the entry is on. For outgoing entries, the one you named on create. For incoming entries, the one Lead matched from the entry. |
| `core_balance_id` | string | The core balance the entry posts to, resolved from the account number. For an account number on a user deposit balance, this is the FBO core balance behind it. |
| `core_transaction_id` | string or null | The core transaction for the original posting. `null` until the entry posts, and `null` on entries whose posting predates core transaction capture. Each return has its own in `returns[]`. |
| `created_at`, `updated_at` | timestamp | RFC 3339, UTC. |
| `status` | enum | See [ACH Statuses](https://docs.lead.bank/v2/products/ach/statuses.md). |
| `amount` | integer | Amount as an integer in minor units. 5000 is \$50.00. |
| `currency_code` | string | ISO 4217. `USD`. |
| `direction` | enum | `outgoing` for entries you originate. `incoming` for entries received from another bank. |
| `delivery_type` | enum | `same_business_day` or `next_business_day`. You set it on outgoing entries. See [ACH timing and availability](https://docs.lead.bank/v2/products/ach/timing.md). |
| `transaction_type` | enum | `credit` pushes funds to the counterparty. `debit` pulls funds from the counterparty. |
| `sec_code` | enum | `CCD`, `PPD`, `TEL`, `WEB`, `CIE`, or, on incoming entries only, `IAT`. |
| `statement_descriptor` | string | The description that appears on the counterparty's statement. On a reversing entry Lead sets it to `REVERSAL`. |
| `record_details` | object | Fields from the Nacha entry and batch records. See [The record details block](#the-record-details-block). |
| `counterparty` | object | The other party's bank account. See [The counterparty block](#the-counterparty-block). |
| `returns` | array of objects | Every return, dishonored return, and contested return on the entry, oldest first. Empty when there are none. See [The returns block](#the-returns-block). |
| `reversal` | object or null | Set on both sides of a reversal: the entry that was reversed and the entry that reversed it. See [The reversal block](#the-reversal-block). |
| `rejection` | object or null | Set when `status` is `rejected`. See [The rejection block](#the-rejection-block). |
| `correction` | object or null | Set when a Notification of Change has arrived for the entry. See [The correction block](#the-correction-block). |
| `iat_details` | object or null | Set on incoming `IAT` entries only. See [The IAT details block](#the-iat-details-block). |
| `metadata` | object | Key-value pairs for your own use. Lead doesn't read them. Update with `PATCH`. |

## The record details block

The table lists the fields in the record details block.

| Field | Type | Description |
| - | - | - |
| `transaction_code` | enum | The Nacha transaction code as a named value, for example `checking_credit` or `savings_debit`. |
| `company_name` | string | The originating company. Outgoing: set from the originator the account number sends under. Incoming: as received. |
| `company_id` | string | The originating company's ACH company ID. Outgoing: set from the originator. Incoming: as received. |
| `company_discretionary_data` | string or null | Free text from the sender on incoming entries. |
| `effective_date` | date | Outgoing: the date Lead sets from `delivery_type`. Incoming: as received. |
| `settlement_date` | date | The date by which funds must be posted to the counterparty's account. |
| `individual_id` | string or null | Your identifier for the receiver, if you sent one. |
| `receiver_name` | string or null | The receiver's name as it appears in the entry. |
| `descriptive_date` | string or null | The descriptive date you sent, if any. |
| `additional_information` | string or null | The addenda text on the entry. This field mirrors the Nacha addenda record. |
| `trace_number` | string | The trace number assigned by the originating bank. Outgoing: generated by Lead at submission. Incoming: as received. |

## The counterparty block

The table lists the fields in the counterparty block.

| Field | Type | Description |
| - | - | - |
| `name` | string | The counterparty's name. |
| `account_number` | string | The counterparty's account number. |
| `routing_number` | string | The counterparty's routing number. |
| `account_type` | enum | `checking` or `savings`. |

## The returns block

Each entry in `returns[]` is one return event on the ACH. A return, a dishonored return, and a contested return are all returns. The `return_code` tells you which.

| Field | Type | Description |
| - | - | - |
| `type` | enum | `return`, `dishonored_return`, or `contested_return`. Determined by `return_code`. |
| `status` | enum | The status of this return event. Uses the same values as the ACH `status`. A return Lead declined after review is `rejected` here while the parent entry stays `posted`. |
| `return_code` | string | The Nacha return reason code, for example `R01`. `R61` to `R70` are dishonored returns. `R71` to `R77` are contested returns. |
| `reason` | string | Short description of the return code. |
| `details` | string or null | Free text from the return addenda, when the returning party provided it. |
| `trace_number` | string or null | The trace number of the return entry, assigned by the bank that sent it. |
| `core_transaction_id` | string or null | The core transaction this return posted. `null` until it posts, and `null` on a return that was declined. |

## The reversal block

The table lists the fields in the reversal block.

| Field | Type | Description |
| - | - | - |
| `reason` | enum | Why the entry was reversed: `duplicate`, `receiver_incorrect`, `amount_incorrect`, `debit_too_early`, or `credit_too_late`. |
| `linked_ach_id` | string | On the original entry, the ID of the reversing entry. On the reversing entry, the ID of the original. |

`POST /v2/ach/{ach_id}/reverse` takes `reason` with the same values and creates a new outgoing entry in the opposite direction for the same amount. There is no free-text field, because Nacha reversals don't have one.

## The rejection block

The table lists the fields in the rejection block.

| Field | Type | Description |
| - | - | - |
| `reason` | enum | Why Lead rejected the entry. A closed set of values owned by Lead, with `other` for conditions that fit nothing else. |
| `details` | string or null | Free text about the rejection, for example which account number was inactive. |

## The correction block

Set when the counterparty's bank sends a Notification of Change. Update your counterparty records from it before your next entry to that counterparty.

| Field | Type | Description |
| - | - | - |
| `account_number` | string or null | The corrected account number. |
| `routing_number` | string or null | The corrected routing number. |
| `account_type` | enum or null | The corrected account type, `checking` or `savings`. |

## The IAT details block

Set on incoming `IAT` entries only. Lead doesn't originate IAT.

| Field | Type | Description |
| - | - | - |
| `transaction_type_code` | enum | The IAT transaction type, for example `business`. |
| `destination_country` | string | ISO 3166 alpha-2. |
| `originator_currency_code`, `destination_currency_code` | string | ISO 4217. |
| `foreign_trace_number` | string or null | The trace number assigned by the foreign gateway. |
| `additional_information` | string or null | The IAT addenda text. This field mirrors the Nacha addenda record. |
| `originator`, `receiver` | object | Name and address of each party as they appear in the IAT addenda. |
| `originating_financial_institution`, `receiving_financial_institution` | object | Name, identifier type, identifier code, and branch country of each bank. |
| `foreign_correspondent_banks` | array of objects | Any correspondent banks in the chain, each with name, identifier type, identifier code, and branch country. |

## Listing entries

`GET /v2/ach` returns a list (`objects`, `has_more`) sorted newest first. Filters:

| Filter | Matches |
| - | - |
| `account_number_id` | Entries on the account number. |
| `account_number` | Entries on the account number with that number. |
| `counterparty_account_number` | Entries whose counterparty has that account number. |
| `core_transaction_id` | The entry whose top-level `core_transaction_id` or any `returns[].core_transaction_id` equals the value. This is how you go from a core transaction back to the ACH. |
| `direction` | `incoming` or `outgoing`. |
| `status` | One status value. |
| `transaction_type` | `credit` or `debit`. |
| `created_at` | Entries created in the range. |

## Coming from v1

A v2 ACH object replaces the v1 ACH object. Entries created on `/v1/ach` are readable on `/v2/ach`. The create request body is unchanged.

| v1 | v2 | Notes |
| - | - | - |
| `POST /v1/ach` and sub-paths | `POST /v2/ach` and sub-paths | Same request body. |
| `account_id` on the response and as a list filter | Removed | Filter by `account_number_id`. |
| No balance field | `core_balance_id` | Added in v2. The core balance the entry posts to. |
| No ledger link | `core_transaction_id` at the top level and on each `returns[]` entry | Added in v2. One per posting. `null` until posted. |
| No `core_transaction_id` filter | `core_transaction_id` list filter | Added in v2. Matches the top level or any return. |
| `returns[].return_reason` | `returns[].reason` | Renamed. Same content. |
| `returns[].additional_information` | `returns[].details` | Renamed. Same content. |
| `reversal.reversal_reason` | `reversal.reason` | Renamed. Same values. |
| `POST /v1/ach/{ach_id}/reverse` takes `reversal_reason` | `POST /v2/ach/{ach_id}/reverse` takes `reason` | Renamed. Same values. |
| `rejection.reason` is free text | `rejection.reason` is a closed enum with `other` | Entries rejected on v1 return the mapped value when read on v2. `rejection.details` is unchanged. |
| `POST /v1/simulate/ach/{ach_id}/incoming_return` takes `return_additional_information` | `POST /v2/simulate/ach/{ach_id}/incoming_return` takes `details` | The value you send comes back as `returns[].details`. |
| Errors in the v1 shape | Errors in the [v2 shape](https://docs.lead.bank/api-reference/using-the-api/errors-v2.md) | Same validations. |

## Related

* [ACH Overview](https://docs.lead.bank/v2/products/ach/overview.md)
* [ACH Statuses](https://docs.lead.bank/v2/products/ach/statuses.md)
* [Returns, reversals, and exceptions](https://docs.lead.bank/v2/products/ach/exceptions.md)
* [The Account Number Object](https://docs.lead.bank/v2/products/account-number/account-number-object.md)
* [The Core Transaction Object](https://docs.lead.bank/products/core-transaction/core-transaction-object.md)
