Collect ACH payments

Note: Only business accounts have the ability to collect payments.

If you’re looking to collect funds via ACH from other accounts, this guide covers the flow for your use case. Some examples of this scenario include:

  • A subscription-based platform collecting payments from their users
  • A utility service charging their customers for a monthly usage fee
  • A supplier collecting payments from a business

Note that this use case is only available for businesses accounts. For the purposes of this guide, we’ll use an example where you will be building a hypothetical utility bill payment platform. The key players in this scenario are:

  • The utility company (the account collecting funds)
  • The customer (the account being charged)

1. Get your access token

To get started, you’ll need to:

tip
For more detailed instructions, see our Quick start guide.

2. Set up the account collecting funds

Start by creating a Moov account for the utility company. Request the collect-funds capability for the utility company’s account. You will need to submit specific data about the business and its representatives to Moov for verification before the capability is enabled. See our capabilities guide for a list of required information.

Every eligible Moov account automatically comes with a Moov wallet, so you won’t need any additional setup to collect payments with a wallet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
curl -X POST "https://api.moov.io/accounts" \
  -H 'Authorization: Bearer {token}' \
  -H "Content-Type: application/json" \
  -H "Origin: https://api.moov.io" \
  --data-raw '{
    "accountType": "business",
    "profile": {
      "business": {
        "legalBusinessName": "Neighborhood Utility",
        "businessType": "incorporatedNonProfit",
      }
    },
    "foreignId": "your-correlation-id",
    "capabilities": ["collect-funds"]
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const moov = new Moov(credentialsObject);

const account = await moov.accounts.create({
  "accountType": "business",
  "profile": {
    "business": {
      "legalBusinessName": "Neighborhood Utility",
      "businessType": "incorporatedNonProfit",
    }
  },
  "foreignId": "your-correlation-id",
  "capabilities": ["collect-funds"]
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const moov = Moov(token);

const account = await moov.accounts.create({
  "accountType": "business",
  "profile": {
    "business": {
      "legalBusinessName": "Neighborhood Utility",
      "businessType": "incorporatedNonProfit",
    }
  },
  "foreignId": "your-correlation-id",
  "capabilities": ["collect-funds"]
})

3. Set up the account to collect from

Add a Moov account for the customer and provide their legal name and phone or email address.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
curl -X POST "https://api.moov.io/accounts" \
  -H 'Authorization: Bearer {token}' \
  -H "Content-Type: application/json" \
  -H "Origin: https://api.moov.io" \
  --data-raw '{
      "accountType": "individual",
      "foreignID": "your-correlation-id",
        "profile": {
          "individual": {
            "name": {
              "firstName": "Jules",
              "lastName": "Jackson",
            },
            "email": "julesjacksonyoga@moov.io"
          }
        }
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const moov = new Moov({credentialsOjbect});

const account = await moov.accounts.create({
  "accountType": "individual",
  "foreignID": "your-correlation-id",
  "profile": {
    "individual": {
      "name": {
        "firstName": "Jules",
        "lastName": "Jackson",
      },
      "email": "example@mail.com"
    }
  }
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const moov = Moov(token);

const account = await moov.accounts.create({
  "accountType": "individual",
  "foreignID": "your-correlation-id",
    "profile": {
      "individual": {
        "name": {
          "firstName": "Jules",
          "lastName": "Jackson",
        },
        "email": "julesjacksonyoga@moov.io" 
      }
    }
})

4. Add a bank account for the customer

After you’ve added a bank account, the customer must complete the micro-deposit verification process before you can pull funds from their account. Once an external bank account has been verified, Moov will automatically generate payment methods that can be used in the transfer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
curl -X POST "https://api.moov.io/accounts/{account_id}/bank-accounts" \
  -H 'Authorization: Bearer {token}' \
  -H "Content-Type: application/json" \
  -H "Origin: https://api.moov.io" \
  --data-raw '{
    "account": {
      "holderName": "Jules Jackson",
      "holderType": "individual",
      "accountNumber": "0004321567000",
      "bankAccountType": "checking",
      "routingNumber": "123456789"
    }
  }'\
1
2
3
4
5
6
7
8
9
const moov = new Moov(credentialsObject);

const bankAccount = await moov.bankaccounts.link("accountID", {
  "holderName": "Jules Jackson",
  "holderType": "individual",
  "accountNumber": "0004321567000",
  "bankAccountType": "checking",
  "routingNumber": "123456789"
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const moov = Moov(token);

const accountID = accountID;
const bankAccount = {
  "holderName": "Jules Jackson",
  "holderType": "individual",
  "accountNumber": "0004321567000",
  "bankAccountType": "checking",
  "routingNumber": "123456789"
};
moov.accounts.bankAccounts.link({accountID, bankAccount});

Alternatively, you can verify bank accounts with instant account verification (IAV). Read more on how to link bank accounts with MX or Plaid.

5. Get payment methods

Once you’ve set up the utility company and the customer’s accounts, you’re ready to collect a payment. First, you can get a list of the available payment methods from the transfer options endpoint.

When collecting a payment using ACH, you will always use a payment method of type ach-debit-collect for the transfer source. Transfer options will also provide available payment methods for disbursement of the collected funds (for example, the utility company’s Moov wallet).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
curl -X POST "https://api.moov.io/transfer-options" \
  -H 'Authorization: Bearer {token}' \
  -H "Origin: https://api.moov.io" \
  --data-raw '{
    "source": {
      "accountID": "UUID",
    },
    "destination": {
      "accountID": "UUID",
    },
    "amount": {
      "value": 100,
      "currency": "USD"
    }
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
const moov = new Moov(credentialsObject);

const sourceAccountID = 'SOURCE_ACCOUNT_ID';
const destinationAccountID = 'DESTINATION_ACCOUNT_ID';

const options = await moov.transfers.getTransferOptions({
  source: {
    accountID: sourceAccountID,
  },
  destination: {
    accountID: destinationAccountID
  }
  amount: {
    value: 100, 
    currency: "USD"
  }
});

6. Initiate the transfer

Once you’ve selected the payment methods for the transaction, you can initiate a transfer between the two accounts, using the payment method IDs for the wallet and bank account you got earlier in the transfer options request.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
curl -X POST "https://api.moov.io/transfers" \
  -H 'Authorization: Bearer {token}' \
  -H "Origin: https://api.moov.io" \
  -H "X-Wait-For: rail-response" \
  -H 'X-Idempotency-Key: [a valid v4 UUID]' \
  --data-raw '{
    "source": {
      "paymentMethodID": "UUID",
    },
    "destination": {
      "paymentMethodID": "UUID",
    },
    "amount": {
      "value": 100,
      "currency": "USD"
    },
    "description": "Paying Jules for last 4 classes"
  }'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const moov = new Moov(credentialsObject);

const transfer = await moov.transfers.create({
  source: {
    paymentMethodID: "source-payment-method-id",
  },
  destination: {
    paymentMethodID: "destination-payment-method-id",
  },
  amount: {
    value: 100,
    currency: "USD"
  },
});

What’s next

Feel free to explore Moov.js, our in-browser JavaScript SDK. Or, if you’re interested in other use cases, you can dive into our guides: