owned this note
owned this note
Published
Linked with GitHub
---
title: 'ACH Direct Debit'
nonindex: true
hidden: true
tags: ['graphql', 'guides']
---
# ACH Direct Debit
## Introduction
ACH Direct Debit is a payment method that runs on the ACH (Automated Clearing House) network in the United States. It is a financial network used for electronic payments and money transfers which allows customers to pay for transactions by directly debiting their bank account instead of using paper checks, credit card networks, wire transfers, or cash. ACH payments are faster and more reliable than checks, thereby helping to automate and streamline accounting. Now you
---
**Note:** The below section provides information on server side implementation for ACH direct debit using GraphQL. If you are new to GraphQL please refer [About GraphQL](https://graphql.braintreepayments.com/guides/#about-graphql) for more information. Also, for details on existing Server Support refer [Server Side Implementation](https://developer.paypal.com/braintree/docs/guides/ach/server-side).
For more information on basic concepts refer [Basic Concepts](https://graphql.braintreepayments.com/guides/#basic-concepts).
---
## Verification Methods
In order to be able to accept ACH payments from your customers, their bank account information needs to go through a verification process. The following are the various methods of verifying the customer bank account:
* [Tokenizing](#Tokenizing)
* Tokenizing without verification.
* Tokenizing with verification.
* [Vaulting](#Vaulting)
* Vaulting with verification.
* Vaulting without verification.
* Verifying
* Verification with network check.
* Verification with micro transfers.
* Verification with independent check.
* Transacting
## Tokenizing
Tokenizing is a process of exchanging raw payment information for generating a secure, one-time-use token referred to as a payment method nonce.
### How it works?
ACH Payment Tokenization replaces sensitive account and routing number data with a random string of alpha-numeric data. This data is called a reference token and is stored in lieu of full sensitive data. When the bank account is future billed, the token is generated and sent. The ACH processor has the full account and routing number securely stored and using the matching token the ACH transaction is processed.
### Methods to tokenize for ACH Integration
There are two ways to tokenize:
#### 1. Tokenizing without verification
A bank account can be tokenized by following the below steps:
##### Pre-requisites
As a pre-requistie to tokenize without verification, the one-time token or the nonce needs to be utilized to vault the bank account. The same must be verified successfully to render the resulting nonce transactable.
##### Steps:
After successfully vaulting the bank account, the following information can be collected to tokenize without verification. Choose any of the following methods:
* Customers Account Information
* Routing Numbers
**(TW: CAN PROVIDE MORE INFO ON WHAT TO DO AFTER THE INPUTS ARE COLLECTED)**
#### 2. Tokenizing with verification
(TW: MISSING INFORMATION- NEED INPUTS)
### Process to Generate a Token
ACH datapoints consist of a bank account number and routing number. The routing number identifies the consumer or businesses bank. These numbers be replaced with a reference token. The token is then stored with the customer data and when payment is collected or disbursed the reference token is sent as part of the transaction string.
In order to generate a token follow the steps mentioned below:
1. Utilize the [tokenizeUsBankAccount](https://graphql.braintreepayments.com/reference/#Mutation--tokenizeUsBankAccount) mutation to tokenize a US bank account.
---
**Note:** The ACH tokenization gateway has the full account and routing numbers vaulted.
---
2. Provide the bank account details as [input](https://graphql.braintreepayments.com/reference/#input_object--tokenizeusbankaccountinput) in [usBankAccount](https://graphql.braintreepayments.com/reference/#input_object--tokenizeusbanklogininput).
---
**Note:** The resulting token that represents the bank account can be found in *data.tokenizeUsBankAccount.paymentMethod.id.* In example above, it's the string with "tokenusbankacct_" prefix.
---
*Request body*
```
mutation TokenizeUsBankAccount($input: TokenizeUsBankAccountInput!) {
tokenizeUsBankAccount(input: $input) {
clientMutationId
paymentMethod {
id
usage
createdAt
details {
... on UsBankAccountDetails {
accountholderName
accountType
bankName
last4
routingNumber
verified
achMandate {
acceptedAt
acceptanceText
}
}
}
}
}
}
```
*Inputs*
```
{
"input": {
"usBankAccount": {
"routingNumber": "021000021",
"accountNumber": "9876543210",
"accountType": "CHECKING",
"achMandate": "I agree to give away all my money",
"individualOwner": {
"firstName": "Busy",
"lastName": "Bee"
},
"billingAddress": {
"streetAddress": "111 Main St",
"extendedAddress": "#7",
"city": "San Jose",
"state": "CA",
"zipCode": "94085"
}
}
}
}
```
*Response*
```
{
"data": {
"tokenizeUsBankAccount": {
"clientMutationId": null,
"paymentMethod": {
"id": "tokenusbankacct_rest_of_token",
"usage": "SINGLE_USE",
"createdAt": "2022-08-10T23:19:17.117000Z",
"details": {
"accountholderName": "Busy Bee",
"accountType": "CHECKING",
"bankName": "JPMORGAN CHASE",
"last4": "3210",
"routingNumber": "021000021",
"verified": false
}
}
}
},
"extensions": {
"requestId": "cfcc38fe-6e93-4fcf-aa1a-a62e2f37c676"
}
}
```
## Vaulting
Vaulting is the process of exchanging a one-time-use payment method nonce for a peristent payment method token. Valuting can be configured with our without verification. Refer the below sections:
## Vaulting with verification
When vaulting a bank account, you can choose to specify a verification method. This creates a vaulted payment method and initiates a verification in a single step.
---
**Note:** This method of vaulting a bank account will be tansactable only if the verification is successful. If the verification fails, the same method can be repeated to get a successful verification.
---
### Process
Follow the steps below:
1. Utilise [vaultUsBankAccount](https://graphql.braintreepayments.com/explorer/#:~:text=.-,vaultUsBankAccount,-Mutation) mutation for vaulting.
2. Provide the [input](https://graphql.braintreepayments.com/reference/#input_object--vaultusbankaccountinput). For the inpu, it is mandatory to provide at least a single-use ACH [paymentMethod](https://graphql.braintreepayments.com/reference/#scalar--id).
---
Note: You can define any of the supported [Verification Methods](https://graphql.braintreepayments.com/reference/#enum--usbankaccountverificationmethod) for verifying the bank account information.
---
*Request body*
```
mTo vault an ACH payment method, you should use vaultUsBankAccount mutation.
For input you would provide at least a single-use ACH paymentMethod. Optionally, you can also provide a verificationMethod which specifies the way in which you want the given bank account verified.utation VaultUsBankAccount($input: VaultUsBankAccountInput!) {
vaultUsBankAccount(input: $input) {
clientMutationId
paymentMethod {
id
legacyId
details {
... on UsBankAccountDetails {
accountholderName
accountType
bankName
last4
routingNumber
verified
achMandate {
acceptedAt
acceptanceText
}
}
}
}
verification {
id
status
}
}
}
```
*Inputs*
```
{
"input": {
"paymentMethodId": "tokenusbankacct_bf_4t32qt_b2p7v9_x7gcpk_q7rjvf_2n3",
"verificationMerchantAccountId": "paypal",
"verificationMethod": "MICRO_TRANSFERS"
}
}
```
*Response*
```
{
"data": {
"vaultUsBankAccount": {
"clientMutationId": null,
"paymentMethod": {
"id": "cGF5bWVudG1ldGhvZF91c2JfYnQ4a3BrNg",
"legacyId": "bt8kpk6",
"details": {
"accountholderName": "Busy Bee",
"accountType": "CHECKING",
"bankName": "JPMORGAN CHASE",
"last4": "3210",
"routingNumber": "021000021",
"verified": false,
"achMandate": {
"acceptedAt": "2022-08-11T06:26:34.000000Z",
"acceptanceText": "I agree to give away all my money today."
}
}
},
"verification": {
"id": "dXNiYW5rYWNjb3VudHZlcmlmaWNhdGlvbl85Y3F2M3QzOA",
"status": "PENDING"
}
}
},
"extensions": {
"requestId": "126e6b6f-3205-42c7-b4b7-844c42b333f2"
}
}
```
## Vaulting without verification
You can also vault a bank account without specifying a verification method. This will vault the payment method as usual, but no verification will be attempted. However, as mentioned in the previous section, this payment method will not be transactable until it has a subsequent successful verification.
If you prefer to perform the verification on your own, the [Verification Method](https://graphql.braintreepayments.com/reference/#enum--usbankaccountverificationmethod) should be set as INDEPENDENT_CHECK.
## Verifying
To verify an US bank account, you should use [verifyUsBankAccount](https://graphql.braintreepayments.com/reference/#Mutation--verifyUsBankAccount) mutation.
For [input](https://graphql.braintreepayments.com/reference/#input_object--verifyusbankaccountinput) you would provide at the minimum [paymentMethodId](https://graphql.braintreepayments.com/reference/#scalar--id) and [verificationMethod](https://graphql.braintreepayments.com/reference/#enum--usbankaccountverificationmethod).
*Request body*
```
mutation VerifyUsBankAccount($input: VerifyUsBankAccountInput!) {
verifyUsBankAccount(input: $input) {
clientMutationId
verification {
id
legacyId
status
merchantAccountId
createdAt
gatewayRejectionReason
paymentMethod {
id
}
processorResponse {
legacyCode
message
cvvResponse
avsPostalCodeResponse
avsStreetAddressResponse
}
}
}
}
```
*Inputs*
```
{
"input": {
"paymentMethodId": "cGF5bWVudG1ldGhvZF91c2JfNGt4ZjI5Ng",
"verificationMethod": "INDEPENDENT_CHECK"
}
}
```
*Response*
```
{
"data": {
"verifyUsBankAccount": {
"clientMutationId": null,
"verification": {
"id": "dXNiYW5rYWNjb3VudHZlcmlmaWNhdGlvbl9qeTZ2Zjg5eA",
"legacyId": "jy6vf89x",
"status": "VERIFIED",
"merchantAccountId": "paypal",
"createdAt": "2022-08-11T05:06:10.000000Z",
"gatewayRejectionReason": null,
"paymentMethod": {
"id": "cGF5bWVudG1ldGhvZF91c2JfNGt4ZjI5Ng"
},
"processorResponse": {
"legacyCode": "1000",
"message": "Approved",
"cvvResponse": null,
"avsPostalCodeResponse": null,
"avsStreetAddressResponse": null
}
}
}
},
"extensions": {
"requestId": "c33bf5ea-e978-4c03-82d2-1a13067f9a78"
}
}
```
To check for successful verification, you should examine [verifyUsBankAccount.verification.processorResponse.message](https://graphql.braintreepayments.com/reference/#object--verificationprocessorresponse) and look for "*Approved*". If verification has failed, some other message is returned, such as "*Processor Network Unavailable - Try Again*".
## Methods of Verifying
Braintree’s ACH Direct Debit integration offers the following methods to verify the bank account information provided by the customer for receiving a payment.
* **Network check** – This method instantly verifies the bank account details by utlising the bank account and routing number, as well as personal/business information.
* **Micro-transfers** – issues two separate credits of less than a dollar each to the customer’s bank account and requires the customer to confirm the exact amounts once they’re visible in the account.
* **Independent check** – allows you to use your own verification method that is not listed above and manually mark payment methods as verified.
You can use any combination of these methods in order to meet your business needs. For example, one recommended flow is to use network check as an initial verification method with micro-transfers as a backup option.
## Verification with Micro-deposit
To verify an US bank account using micro-deposit random, small amounts of your choice, you should first use [confirmMicroTransferAmounts](https://graphql.braintreepayments.com/reference/#Mutation--confirmMicroTransferAmounts) mutation to do the first step.
For [input](https://graphql.braintreepayments.com/reference/#input_object--verifyusbankaccountinput) you would provide at the minimum [verificationId](https://graphql.braintreepayments.com/reference/#scalar--id) which is vaultUsBankAccount.verification.id (in the response of vaultUsBankAccount mutation) and [amountInCents](https://graphql.braintreepayments.com/reference/#scalar--int) which is an array of integers. For instance, to specify 17 cents and 44 cents, you would provide [17, 44].
*Request body*
```
mutation ConfirmMicroTransferAmounts($input: ConfirmMicroTransferAmountsInput!) {
confirmMicroTransferAmounts(input: $input) {
verification {
id
paymentMethod {
id
usage
}
merchantAccountId
status
processorResponse {
message
cvvResponse
avsPostalCodeResponse
avsStreetAddressResponse
}
networkResponse {
code
message
}
gatewayRejectionReason
}
status
}
}
```
*Inputs*
```
{
"input": {
"verificationId": "dXNiYW5rYWNjb3VudHZlcmlmaWNhdGlvbl85Y3F2M3QzOA",
"amountsInCents": [17, 44]
}
}
```
*Response*
```
{
"data": {
"confirmMicroTransferAmounts": {
"verification": {
"id": "dXNiYW5rYWNjb3VudHZlcmlmaWNhdGlvbl85Y3F2M3QzOA",
"paymentMethod": {
"id": "cGF5bWVudG1ldGhvZF91c2JfYnQ4a3BrNg",
"usage": "MULTI_USE"
},
"merchantAccountId": "paypal",
"status": "PENDING",
"processorResponse": {
"message": "Approved",
"cvvResponse": null,
"avsPostalCodeResponse": null,
"avsStreetAddressResponse": null
},
"networkResponse": {
"code": null,
"message": null
},
"gatewayRejectionReason": null
},
"status": "AMOUNTS_DO_NOT_MATCH"
}
},
"extensions": {
"requestId": "6366e6c2-192c-4bac-b87f-3149eecec7b7"
}
}
```
## Checking verification status
To check for successful verification, you should examine [verifyUsBankAccount.verification.processorResponse.message](https://graphql.braintreepayments.com/reference/#object--verificationprocessorresponse) and look for "*Approved*". If verification has failed, some other message is returned, such as "*Processor Network Unavailable - Try Again*".
## Retrying verification
Sometimes verification would fail. You can retry verification by sending the the previous request again or use the previous request but change the [verificationMethod](https://graphql.braintreepayments.com/reference/#enum--usbankaccountverificationmethod). For example, previously, NETWORK_CHECK was used and failed with a message "*No Data Found - Try Another Verification Method*", on a retry, you should change it to MICRO_TRANSFERS as an alternative.
## Common errors
Note that each tokenized US bank account can only be vaulted once. If you attempt to vault the same token more than once, you will get the following error. Also note that the ACH payment method and US bank account are used interchangably in this document.
```
{
"errors": [
{
"message": "Cannot use a single-use payment method more than once.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"vaultUsBankAccount"
],
"extensions": {
"errorClass": "VALIDATION",
"errorType": "user_error",
"inputPath": [
"input",
"paymentMethodId"
],
"legacyCode": "93107"
}
}
],
"data": {
"vaultUsBankAccount": null
},
"extensions": {
"requestId": "ba53c8e6-43b2-464a-b0f8-bc1599b96af7"
}
}
```
If you do not provide [verificationMethod](https://graphql.braintreepayments.com/reference/#enum--usbankaccountverificationmethod) in the inputs, you will get the following error.
```
{
"errors": [
{
"message": "Variable 'input' has an invalid value: Field 'verificationMethod' has coerced Null value for NonNull type 'UsBankAccountVerificationMethod!'",
"locations": [
{
"line": 1,
"column": 29
}
]
}
],
"extensions": {
"requestId": "7fd3e425-ff70-43bc-8cb5-9014fdedccff"
}
}
```