Guides
Explanatory and how-to content
API Reference
Technical documentation
Changelog
Release notes
Dashboard
Manage your account
Status
Service status

Setting up ACH debits

Setting up ACH debits for consumer accounts requires three steps. First, you need to make sure that you have obtained authorization from your end user. Second, you need to verify that the user has access to the provided account and that it is setup to process ACH debits. Third, you need to initiate the actual ACH debit. In this guide, we’ll walk you through each of these steps to ensure your process aligns with industry standards and regulations.

Receiving authorization

Before initiating ACH debits, you must obtain explicit authorization from your customer. Most often this looks like a written authorization signed by the customer. While debiting a business is relatively straightforward, debiting a consumer is more nuanced, requiring the authorization to be specified as either a one time, recurring, or standing authorization (each with their own rules). You can learn more about the differing requirements for these authorizations here.

Regardless of type, the authorization must include the following:

  • The name or identity of the person being debited
  • The account that will be debited
  • The transaction amount or a variable amount range
  • The transaction frequency (one-time or recurring)
  • The date of the first transaction (for recurring payments)
  • Language on how to revoke the authorization (including the time and manner in which the communication must occur)
Retention and record keeping

You are required to retain a copy of the authorization for at least two years from the termination date. In the event of a dispute, you will be required to provide proof of authorization. Consider implementing an automated system for managing authorizations, with encryption to ensure customer data privacy.

Verify account access

After obtaining authorization, you need to verify that the customer has access to the account that will be debited. This can commonly happens in two ways:

  • Instant verification through a third party service like Plaid, Yodlee, MX, Finicity, Teller, MoneyKit, etc.
  • Manually verify with ACH or Real-Time Payments micro-deposits.

Setting up account verification with a third party service

The obvious benefit of using a service like Plaid or Yodlee is that customers will be able to verify access to their account relatively quickly, usually requiring them to simply log in to their bank account and confirm access. However, you’ll need to set up a new integration. At a top level, this integration will look like:

  • Integrate the API: Start by integrating the API provided by Plaid or Yodlee to generate an authentication token.
  • Implement the hosted flow: Use the third-party-hosted flow—Plaid Link or Yodlee FastLink—to securely guide users through the authentication process.
  • Customize the interface: Tailor the appearance of the flow to match your brand, ensuring a seamless user experience.
  • Authenticate users: Once users authenticate, both services return an access token, confirming their access.
  • Retrieve account information : Retrieve limited data about the user’s bank accounts (e.g., account type, account number, routing number) to facilitate a transfer.

You can learn more by reading Plaid’s Documentation and Yodlee’s Documentation.

Building ACH microdeposit verification

Alternatively, you can verify a customer’s access to an account by using ACH microdeposits. This process usually takes 1-2 days to complete. You can also use Real-Time Payments to send microdeposits in a few seconds, but are limited to a subset of banks that currently support this financial network.

1. Send two microdeposits

Start by initiating two small ACH credits with random amounts (e.g., $0.06 and $0.32) to the user’s account. These microdeposits serve as both a verification mechanism and a way to validate that the account is open and can receive ACH transfers. Make sure to notify users to monitor their bank account for these deposits, which typically appear within 1-2 business days.

As of September 2024, microdeposits must be identified as “Micro-Entries” by setting the company_entry_description field to ACCTVERIFY, in compliance with Nacha’s rules. Additionally, the company_name must be easily recognizable and consistent with the name used for future entries.

await increase.achTransfers.create({ account_id: 'account_in71c4amph0vgo2qllky', amount: 6, currency: 'USD', individual_name: 'Ian Crease', account_number: '987654321', routing_number: '101050001', company_name: 'Increase', company_entry_description: 'ACCTVERIFY', });
await increase.achTransfers.create({ account_id: 'account_in71c4amph0vgo2qllky', amount: 32, currency: 'USD', individual_name: 'Ian Crease', account_number: '987654321', routing_number: '101050001', company_name: 'Increase', company_entry_description: 'ACCTVERIFY', });
2. Initiate an offset debit

To balance your ledger, you can optionally initiate a single ACH debit for the total amount of the microdeposits (e.g., $0.38). Note that this debit transfer may not exceed the value of the credit amounts and must be submitted simultaneously within the same file to the receiving institution.

await increase.achTransfers.create({ account_id: 'account_in71c4amph0vgo2qllky', amount: -38, currency: 'USD', individual_name: 'Ian Crease', account_number: '987654321', routing_number: '101050001', company_name: 'Increase', company_entry_description: 'ACCTVERIFY', });
3. Evaluate response from the Receiving depository institution

If the account credentials are valid, the transfers will successfully post. However, if there is a problem with the credentials, the receiving bank will return the transfer. In this instance, the associated ACH Transfer object’s status will be updated to returned and a return_reason_code will be included with additional information—for example R02 (The account is closed).

Because the receiving institution can return either the credit or debit transfers, account validation can vary depending upon a few factors. The following table outlines a few common scenarios.

CreditDebitDescription
PostedPostedFull validation: The account is valid for future authorized ACH credits or debits.
PostedR01, R09Full validation: The account has been overdrawn by the ACH debit. However, the account is still valid for future authorized credits or debits.
Posted or R20, R23R16, R29Partial validation: The account has blocked all ACH debits. However, the account is valid for authorized credits.
Posted or R20, R23R20Partial validation: The account type does not accept ACH debits. However, the account is valid for authorized credits.
R23R05, R07, R10, R11Failed validation: The transactions have not been authorized by the account holder. No further attempts should be made until a new authorization has been obtained.
R02, R03, R04R02, R03, R04Failed validation: The account is either closed or does not exist
Any except R20, R23Any except R01, R09Failed validation: There is likely an error in the entries

For a full list of ACH return codes and their descriptions, view our documentation on Returns.

4. Collect confirmation from the user

Once the microdeposits have settled, ask the user to confirm the exact deposit amounts. This can be done via:

  • A secure input field in your application.
  • A phone or email response, depending on your process.

Ensure that this step is straightforward for users to complete, as delays in their response can further impact onboarding time.

Initiating ACH debits

Now that you’ve obtained authorization from the customer and proved they have access to an account, you can initiate your ACH debit (per your authorization). For more information you can view the lifecycle of an ACH Transfer or view our guide on sending ACH debits.