Skip to main content

Bank Elements

Bank elements let you collect account numbers and routing numbers in your own form without those values ever appearing in your JavaScript or reaching your server. Each field is an isolated iframe; tokenization happens inside the Ozura-origin tokenizer frame.
OzuraPay does not currently support bank account payments. The bank token is for use with your own ACH-capable payment processor via the Proxy.

Field Types

typeDescription
accountNumber4–17 digit bank account number. Rendered as a password-type input to prevent shoulder surfing.
routingNumber9-digit US ABA routing number. Validated against the standard ABA checksum algorithm.

Creating and Mounting

import { OzVault, OzError } from '@ozura/elements';

const vault = new OzVault('YOUR_API_KEY', { pubKey: 'YOUR_PUB_KEY' });

const accountEl = vault.createBankElement('accountNumber');
const routingEl = vault.createBankElement('routingNumber');

accountEl.mount('#account-number');
routingEl.mount('#routing-number');
With options:
const style = {
  base:        { fontSize: '15px', color: '#1a1a2e', padding: '12px 14px' },
  focus:       { caretColor: '#6366f1' },
  placeholder: { color: '#94a3b8' },
};

const accountEl = vault.createBankElement('accountNumber', { style });
const routingEl = vault.createBankElement('routingNumber', { style });

createBankElement Options

vault.createBankElement(type: BankElementType, options?: ElementOptions): OzElement
OptionTypeDescription
styleElementStyleConfigPer-element style overrides. See Styling.
placeholderstringPlaceholder text shown inside the field
disabledbooleanMount the field in a disabled state

Tokenizing

Call createBankToken() after the user has filled both fields. firstName and lastName are required — they are included in the vault record alongside the account data.
document.getElementById('submit-btn').addEventListener('click', async () => {
  const firstName = document.getElementById('first-name').value.trim();
  const lastName  = document.getElementById('last-name').value.trim();

  try {
    const { token, bank } = await vault.createBankToken({ firstName, lastName });

    // token          — vault token, pass to your backend
    // bank.last4     — last 4 digits of account number (safe to display)
    // bank.routingNumber — the routing number

    await fetch('/api/ach', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token }),
    });
  } catch (err) {
    if (err instanceof OzError) {
      console.error(err.message, err.errorCode);
    }
  }
});

createBankToken options

vault.createBankToken(options: BankTokenizeOptions): Promise<BankTokenResponse>
OptionTypeRequiredDescription
firstNamestringAccount holder first name
lastNamestringAccount holder last name

BankTokenResponse

{
  token: string;     // vault token — pass to your backend
  bank?: {
    last4:         string; // last 4 digits of account number
    routingNumber: string; // the routing number
  };
}

Events

Bank elements emit the same events as card elements:
accountEl.on('change', ({ complete, valid, error }) => {
  const wrap   = document.getElementById('account-wrap');
  const errMsg = document.getElementById('account-error');

  wrap.classList.toggle('complete', complete && valid);
  wrap.classList.toggle('invalid',  !valid && error != null);
  errMsg.textContent = error ?? '';
});

accountEl.on('focus', () => document.getElementById('account-wrap').classList.add('focused'));
accountEl.on('blur',  () => document.getElementById('account-wrap').classList.remove('focused'));

Error messages

FieldErrorCondition
accountNumber"Invalid account number"Not 4–17 digits
routingNumber"Invalid routing number"Not 9 digits or fails ABA checksum

Gating the submit button

const state = { accountReady: false, routingReady: false };

function updateButton() {
  document.getElementById('submit-btn').disabled =
    !(state.accountReady && state.routingReady);
}

accountEl.on('change', ({ complete, valid }) => {
  state.accountReady = complete && valid;
  updateButton();
});

routingEl.on('change', ({ complete, valid }) => {
  state.routingReady = complete && valid;
  updateButton();
});

Displaying Account Info After Tokenization

The bank.last4 and bank.routingNumber values returned by createBankToken() are safe to display to the user as confirmation:
const { token, bank } = await vault.createBankToken({ firstName, lastName });

if (bank) {
  document.getElementById('confirm-text').textContent =
    `Account ending in ${bank.last4} • Routing ${bank.routingNumber}`;
}

Validation Details

Account number

  • Accepts 4–17 digits
  • All non-digit characters are stripped as the user types
  • Rendered as a password field (dots, not plain text) to prevent shoulder surfing

Routing number

  • Must be exactly 9 digits
  • Validated with the standard ABA routing number checksum: (3×(d1+d4+d7) + 7×(d2+d5+d8) + (d3+d6+d9)) mod 10 === 0
  • Invalid routing numbers are flagged immediately when the 9th digit is entered

Accessing an Existing Bank Element

const existing = vault.getBankElement('accountNumber');
// returns the OzElement or null if not yet created

Teardown

// Destroy the vault and all its iframes when the component unmounts
vault.destroy();

Next Steps