Capture bank details¶
Collecting bank details for ACH works the same way as capturing a card: an Aptean-hosted iFrame takes the account and routing number, and hands you back a token.
Everything on this page mirrors the card guide. The differences are the component you create, the div you mount into, and the validation errors you can get back.
Note
This collects US bank details — account number and ABA routing number. The token
type is payment-bank-us.
Build the page¶
1. Add a container and a button¶
2. Load the SDK¶
| Environment | Script URL |
|---|---|
| Staging | https://stg.js.apteansharedservices.com/apteanpay-js/v1 |
| Production | https://js.apteansharedservices.com/apteanpay-js/v1 |
3. Initialise, mount, and handle the token¶
<script>
const apteanPay = ApteanPay(
'<your api key>', // x-aptean-apim
'<your product id>', // your ERP product id
'<your tenant id>' // x-aptean-tenant
);
const customStyle = {
styles: {
base: {
'border-radius': '4px',
height: '56px',
'font-size': '16px'
}
}
};
const bankComponentOptions = {
customStyle,
showPlaceholders: true,
showErrorMessages: true
};
const components = apteanPay.components({});
// Note the different factory method and its two arguments.
const bankComponent = components.createBank({}, bankComponentOptions);
bankComponent.mount(
'bankIframe', // the div id — no '#'
'#submitButton' // the button — with '#'
);
apteanPay.createTokenCallback(
bankComponent,
{
name: '<account holder name>', // required
addressLine1: '<address line 1>',
addressLine2: '<address line 2>',
addressCity: '<city>',
addressState: '<state>',
addressZip: '<postal code>', // required
addressCountry: '<ISO country code>', // required
emailAddress: '<email>', // required
phoneCountryCode: '<phone country code>',
phoneNumber: '<phone number>'
},
function (token, error) {
if (error) {
console.log(error);
return;
}
console.log(token);
}
);
</script>
Warning
The card component is created with components.create('card', options). The bank
component is created with components.createBank({}, options) — a different method, and the
options are the second argument, not the first.
4. Open the page¶

Enter the test bank account and routing number and click the button.
What you get back¶
{
"id": "183075a2-41f1-4ba1-895f-e320336c3f59",
"created": 1746614580,
"livemode": false,
"type": "payment-bank-us",
"used": false
}
On failure:
| Error message | What it means |
|---|---|
Parameter failed UI validation : routing-number |
The routing number is not a valid ABA number. |
Parameter failed UI validation : account-number |
The account number is not valid. |
Expected value in [PR, PS, PT, …] |
addressCountry is not a recognised ISO country code. |
Invalid postal code for the country '{addressCountry}' |
addressZip does not match the format for that country. |
ACH behaves differently from cards¶
This matters more than the API difference:
- ACH is not instant. A card authorisation succeeds or declines in seconds. An ACH debit is
submitted, sits in
PENDING, and can fail days later — insufficient funds, closed account, or the payer disputing it. - A successful
createPaymentis not settled money. Do not release goods on the strength of aPENDINGACH payment. See Payment status. - Your merchant account must be enabled for bank payments. If ACH is not enabled for your tenant the token will be created but the payment will be refused. Ask Aptean support to check.
What to do with the token¶
The same as for a card — the token is short-lived and single-use:
- Charge it now — Create a payment, as
paymentMethodId. - Keep it for later — Saved payment methods.