# 

ACH moves money directly between US bank accounts over a network operated by
NACHA. It is the rail behind direct deposit and most recurring bill payment.

Compared with cards, the trade is cost against certainty.

|  | Card | ACH |
|  --- | --- | --- |
| Cost | A percentage of the amount | Usually a flat fee |
| Authorization | Real time, from the issuer | None. There is no balance check |
| Finality | Decline arrives in the response | A return can arrive days later |
| Good for | Any amount, immediate fulfillment | Large or recurring amounts, B2B |


## There is no authorization step

This is the difference that matters most, and it catches card-shaped
integrations.

A card transaction asks the issuer a question and gets an answer.
**An ACH debit asks nobody.**
It is submitted, it settles, and only afterwards can the receiving
bank reject it — because the account was closed, the balance was short, or the
customer revoked authorization.

```mermaid
---
config:
  theme: 'neutral'
---
flowchart LR
    A[Submit debit] --> B[Approved]
    B --> C[Settles]
    C --> D{Receiving bank}
    D -->|accepts| E[Funds are yours]
    D -->|rejects, days later| F[Return]
```

So an approved ACH transaction is **provisional**. Do not treat it as final for
anything expensive to reverse until returns have had time to arrive.

## SEC codes

Every ACH entry carries a Standard Entry Class code declaring how the customer
authorized it. It is a compliance statement, not a preference — send the one that
matches what actually happened.

| Code | Authorization |
|  --- | --- |
| `WEB` | Consumer authorized over the internet. The default |
| `PPD` | Consumer authorized in writing |
| `TEL` | Consumer authorized by telephone |
| `CCD` | Business to business |
| `POP` | Check converted at the point of sale |
| `BOC` | Check converted after the sale |


Keep evidence of the authorization. A disputed debit is resolved by producing it.

## Returns

A return is NACHA's mechanism for rejecting an entry after the fact. Each carries
a three-character code — `R01` insufficient funds, `R02` account closed, `R10`
customer advises unauthorized, and so on.

Four fields on the transaction report it: `is_returned`, `returned_at`,
`return_code` and `return_reason`.

**`return_code` and `return_reason` are omitted rather than null** when there has
been no return, which is nearly always. Read them defensively.

There are no webhooks, so finding returns means polling. See
[Accept an ACH payment](/docs/payments/accept-an-ach-payment).

## Direction

ACH runs both ways, and the gateway exposes both:

* **Debit** — pull funds in. `type` of `SALE`.
* **Credit** — push funds out. `type` of `PAYOUT`. See
[Send a payout](/docs/payments/send-a-payout).


A bank account accepts those two types and no others. There is no ACH
authorization, so `AUTH` is rejected.

## Next steps

* [Accept an ACH payment](/docs/payments/accept-an-ach-payment)
* [Send a payout](/docs/payments/send-a-payout)
* [Find and report on transactions](/docs/after-the-payment/find-and-report-on-transactions)