An ACH debit pulls funds from a customer's checking or savings account. It costs less than a card payment and suits large or recurring amounts, but it settles more slowly and it can come back days later as a return.
ACH runs through VeriCheck. Card transactions run through TSYS. A merchant account is configured for one or the other, so the payment method and the credentials have to agree.
- Your
Api-KeyandClient-Id— see Authentication - A processor integration configured for ACH
- The customer's authorization to debit the account, in a form the SEC code below describes
POST /v1/transactions with type set to SALE and a bank account as the payment method.
ACH asks for more required fields than a card does. All six of these must be present:
| Field | Notes |
|---|---|
payment_method.type | ACH |
payment_method.routing_number | Exactly 9 digits |
payment_method.account_number | 4 to 20 digits |
payment_method.account_type | CHECKING or SAVINGS |
payment_method.first_name | Required, unlike on a card |
payment_method.last_name | Required, unlike on a card |
Two optional fields matter more than they look:
standard_entry_classdefaults toWEB. It declares how the customer authorized the debit, and the right value is a compliance question, not a preference. See the table below.descriptionis at most 30 characters. Only the first 10 reach the customer's bank statement. Left blank, it falls back to the merchant name. Put something recognizable in the first 10 characters or expect disputes.
The Standard Entry Class code records how you obtained authorization. Send the one that matches what actually happened.
| Code | Use it for |
|---|---|
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 |
A bank account accepts type of SALE to pull funds in, and PAYOUT to send them out. There is no ACH authorization, so type: AUTH with a bank account returns 400 with INVALID_ACTION and the message "Payment method not supported for this transaction type".
That also means the capture flow does not apply to ACH. An ACH sale is a single step.
This is the part that catches card-shaped integrations.
A card decline arrives in the response. An ACH return arrives days later, long after you saw APPROVED, and often after the transaction has already settled. Insufficient funds, a closed account, or a customer revoking authorization all surface this way.
So an approved ACH transaction is provisional. Do not treat it as final for anything expensive to reverse — shipping goods, crediting an account balance — until you have given returns time to arrive.
Four fields on the transaction carry it:
| Field | Behavior |
|---|---|
is_returned | true once returned. Always present. Always false on a card |
returned_at | When the processor sent the return. Always present, null if none |
return_code | The three-character NACHA code. Omitted entirely, not null, when there is no return |
return_reason | The same in words. Also omitted rather than null |
Two consequences for your code:
- Read
is_returnedalongsideis_settled, not instead of it. A returned transaction may well have settled first. return_codeandreturn_reasonare absent, not null. Code that readsbody["return_code"]without checking for the key will throw on every transaction that was never returned — which is nearly all of them.
There are no webhooks, so poll GET /v1/transactions to find returns.