Save Bank Accounts
A saved bank account has an id that starts with ba_. You use it to create ACH payments and payouts. Save a bank account in one of two ways:
- Credova Elements captures the bank account in your web app, by manual entry or instant verification. Account numbers never touch your servers.
- The Direct API sends the bank account from your servers.
Before you start
Publishable Key- Loads Credova Elements in the browser. It is safe to put in frontend code.
Secret Key- Authenticates requests from your server. Never send it to the browser.
Request Account Setting Access
Each way to collect a bank account needs an account setting. Request the setting for the option you plan to use:
- Manual Entry needs the
payment-methods:bank-accounts:manual-creationaccount setting type. In the merchant portal, it is theManual Bank Account Creationsetting. - Instant Verification needs the
payment-methods:bank-accounts:verificationaccount setting type. In the merchant portal, it is theBank Account Verificationsetting.
To request a setting, go to the merchant portal and click the Request this feature button next to it.
Alternatively, you can request access via the API.
Your account needs the setting before manual bank account creation or instant bank account verification works.
The payment-methods:bank-accounts:manual-creation setting also lets you send bank account details when you process an ACH payment or an ACH payout. You do not need to create the bank account first.
Save a Bank Account with Credova Elements
Credova Elements gives you two ways to collect a bank account:
- Manual Entry: your customer types the routing number and account number into the Bank Account Elements.
- Instant Verification: your customer connects their bank account and Credova verifies it instantly.
With either option, you create a bank account that holds the non-sensitive information about the bank account. You can safely store the bank account's id value in your database to link it with the appropriate payment or customer association.
When you create the bank account, you can optionally pass in a customer_id to associate with an existing Created Customer and billing_details to remove the requirement to pass them when Creating a Payment.
Configuring Credova Elements
Credova Elements are available for the following technologies. Click below for detailed instructions on how to install and configure them.
Manual Entry
Manual entry captures the routing number and account number in your frontend application and stores them securely in your account.
Adding Bank Account Elements
Once installed and configured, add the Bank Account Elements to your application.
- JavaScript
- React
<form>
<input type="text" id="accountHolderName" placeholder="Account holder name" />
<div id="bankAccount" style="width: 100%;"></div>
</form>
import { PublicSquare } from '@publicsquare/elements-js';
let publicsquare;
let bankAccountElement;
async function init() {
publicsquare = await new PublicSquare().init('<PUBLISHABLE_API_KEY>');
// Creates an Bank Account instance that includes the routing number and account number
bankAccountElement = publicsquare.createBankAccountElement();
bankAccountElement.mount('#bankAccount');
}
init();
import React, { useRef, useState } from 'react';
import {
PublicSquareProvider,
BankAccountElement,
usePublicSquare,
} from '@publicsquare/elements-react';
export default function App() {
const { publicsquare } = usePublicSquare();
// Refs to get access to the Elements instance
const bankAccountRef = useRef(null);
// See below for handleSubmit function
return (
<PublicSquareProvider apiKey={apiKey}>
<form onSubmit={handleSubmit}>
<input
type="text"
name="accountHolderName"
placeholder="Account holder name"
/>
<BankAccountElement
id="bankAccount"
ref={bankAccountRef}
/>
</form>
</PublicSquareProvider>
);
}
Storing Bank Accounts
Now that you are capturing bank account data in your web application, it is time to store the bank account in your account.
To do this, we will call the create bank account method from the SDK, passing the Bank Account Elements as data points in the payload.
Add a submit function along with a button to trigger it:
- JavaScript
- React
async function submit (e: FormEvent<HTMLFormElement>,) {
try {
const formData = new FormData(e.currentTarget)
const account_holder_name = formData.get('accountHolderName');
const routing_number = bankAccountElement.routingNumber.el.value
const account_number = bankAccountElement.accountNumber.el.value
const bankAccount = await publicsquare.bankAccounts.create({
account_holder_name,
routing_number,
account_number,
});
console.log(bankAccount); // e.g { id: 'ba_1234567890', ... }
} catch (error) {
console.error(error);
}
}
async function handleSubmit(e) {
e.preventDefault();
const account_holder_name = e.target.accountHolderName.value;
const routing_number = bankAccountRef.current.routingNumber.el.value
const account_number = bankAccountRef.current.accountNumber.el.value
const bankAccount = await publicsquare.bankAccounts.create({
account_holder_name,
routing_number,
account_number,
});
console.log(bankAccount); // e.g { id: 'ba_1234567890', ... }
}
The created bank account object contains the non-sensitive information about the bank account:
{
"id": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "production",
"customer_id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"billing_details": {
"address_line_1": "111 Colorado Ave.",
"address_line_2": "Apt 403",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
},
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z",
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "checking",
"routing_number": "110000000",
"account_number_last4": "1011"
}
Instant Verification
Instant verification lets your customer connect their bank account so that Credova can verify it instantly, then stores the verified bank account in your account.
Adding Bank Account Verification Elements
Credova has partnered with Flinks to provide a secure way to collect bank accounts. Once installed and configured, add the Bank Account Verification Elements to your application.
- JavaScript
- React
<div id="bank-account-verification-element">
<button
onclick={onConnectBankAccountWithVerification}
>
Connect Bank Account
</button>
</div>
import { PublicSquare } from '@publicsquare/elements-js';
let publicsquare;
let result;
async function init() {
publicsquare = await new PublicSquare().init('<PUBLISHABLE_API_KEY>');
async function onConnectBankAccountWithVerification() {
result = await publicsquare?.bankAccounts.openVerification(
`#${'bank-account-verification-element'}`
)
}
}
await init();
import React, { useRef } from 'react';
import {
PublicSquareProvider,
BankAccountVerificationElement,
usePublicSquare,
} from '@publicsquare/elements-react';
export default function App() {
const { publicsquare } = usePublicSquare();
// Refs to get access to the Elements instance
const bankAccountVerificationElementRef = useRef(null);
return (
<PublicSquareProvider apiKey={apiKey}>
<BankAccountVerificationElement
id="bankAccountVerificationElement"
ref={bankAccountVerificationElementRef}
onVerificationComplete={(result) => {
console.log('Bank account verification completed:', result.bank_account_verification_id);
}}
/>
</PublicSquareProvider>
);
}
Storing Verified Bank Accounts
Now that your customer has verified their bank account information, we need to create a bank account payment method from the results.
To do this, we will call the create bank account method from the SDK passing the bank_account_verification_id, returned from the bank account verification result.
Add a submit function along with a button to trigger it:
- JavaScript
- React
<div id="bank-account-verification-element">
<button
onclick={onConnectBankAccountWithVerification}
>
Connect Bank Account
</button>
</div>
<button id="submit">Submit</button>
import { PublicSquare } from '@publicsquare/elements-js';
let publicsquare;
let result;
async function init () {
publicsquare = await new PublicSquare().init('<PUBLISHABLE_API_KEY>');
async function onConnectBankAccountWithVerification() {
result = await publicsquare?.bankAccounts.openVerification(
`#${'bank-account-verification-element'}`
)
}
document.getElementById("submit").addEventListener("click", submit);
}
async function submit (e: FormEvent<HTMLFormElement>,) {
try {
const bankAccount = await publicsquare?.bankAccounts.create({
bank_account_verification_id: result?.bank_account_verification_id
});
console.log(bankAccount); // e.g { id: 'ba_1234567890', ... }
} catch (error) {
console.error(error);
}
}
await init();
import React, { useRef } from 'react';
import {
PublicSquareProvider,
BankAccountVerificationElement,
usePublicSquare,
} from '@publicsquare/elements-react';
export default function App() {
const { publicsquare } = usePublicSquare();
// Refs to get access to the Elements instance
const bankAccountVerificationElementRef = useRef(null);
const submit = async () => {
try {
const bankAccount = await publicsquare.bankAccounts.create({
bank_account_verification_id: bankAccountVerificationElementRef.current.bank_account_verification_id
});
console.log(bankAccount); // e.g { id: 'ba_1234567890', ... }
} catch (error) {
console.error(error);
}
}
return (
<PublicSquareProvider apiKey={apiKey}>
<BankAccountVerificationElement
id="bankAccountVerificationElement"
ref={bankAccountVerificationElementRef}
onVerificationComplete={(result) => {
console.log('Bank account verification completed:', result.bank_account_verification_id);
}}
/>
<button onClick={submit}>Submit</button>
</PublicSquareProvider>
);
}
The created bank account object contains the non-sensitive information about the bank account:
{
"id": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "production",
"customer_id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"billing_details": {
"address_line_1": "111 Colorado Ave.",
"address_line_2": "Apt 403",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
},
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z",
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "checking",
"routing_number": "110000000",
"account_number_last4": "1011",
"status": "verified"
}
If Credova has not yet received a response from Flinks, the API returns the validation message bank account verification result is still in progress.
Nightly Balance Refresh
We automatically refresh the balance for all verified bank accounts for up to 30 days after verification. To obtain the most recent balance, you can make a call to the Get Bank Account Balance endpoint.
If more than 30 days have passed since the account was verified, you must re-verify the bank account to update its balance.
Save a Bank Account from Your Servers
A restricted key needs the payment-method:write or payment-method:capture permission. Your account also needs the payment-methods:bank-accounts:manual-creation account setting from Request Account Setting Access.
Save a Bank Account
Send the bank account in a POST request to Create Bank Account:
curl 'https://api.publicsquare.com/payment-methods/bank-accounts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "checking",
"routing_number": "110000000",
"account_number": "000123456789",
"customer_id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
}'
The request body accepts these fields:
| Field | Description |
|---|---|
account_holder_name | Name on the bank account. |
account_holder_type | individual or company. |
account_type | checking or savings. |
routing_number | Routing number. |
account_number | Account number. |
customer_id | ID of an existing customer to associate with the bank account. |
billing_details | Billing address for the bank account. |
Send account_holder_name and account_holder_type. Some processors require them.
Bank Account Response
The created bank_account object contains the non-sensitive information about the bank account:
{
"id": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "production",
"customer_id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z",
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "checking",
"routing_number": "110000000",
"account_number_last4": "6789"
}
Store the bank account's id in your database to use it in later payments and payouts.
You do not have to save the bank account first. You can also send the bank account details with the payment.
Conclusion
You have saved a customer's bank account. To use it, follow these guides: