Skip to content

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

<div id="bankIframe"></div>
<button id="submitButton">Submit</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
<script src="https://stg.js.apteansharedservices.com/apteanpay-js/v1"></script>

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

The rendered Aptean Pay bank capture iFrame

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 createPayment is not settled money. Do not release goods on the strength of a PENDING ACH 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: