Documentation Index Fetch the complete documentation index at: https://docs.ozura.com/llms.txt
Use this file to discover all available pages before exploring further.
Bank Payments — Using Elements
Ozura Elements lets you embed account number and routing number fields directly in your own page. Input fields run inside isolated iframes served from Ozura’s domain — raw bank data never leaves those iframes. Tokenization happens in the browser; you receive a vault token that your backend can use to process an ACH payment with your processor.
OzuraPay does not currently support bank account payments. The token you receive is for use with your own ACH-capable payment processor via the Proxy .
Prefer a hosted page? See Checkout (merchants only). Need to tokenize from your backend? See Using the API .
How It Works
Account and routing numbers travel directly from the browser to the Ozura Vault — your server only ever sees a token.
Install the SDK
npm install @ozura/elements
Quick Start
1. Get your credentials
You need both credentials from the Ozura Dashboard . Both must be passed to initialize the SDK — tokenization will fail if either is missing.
Credential Where Used for Vault API Key Dashboard → Vault → Applications Client-side key Vault Pub Key Dashboard → Vault → Applications Authenticates the tokenize request
Testing? For development, you can use this pub key:pk_prod_jys4le1jgncomgda_L8HbeakKLNRWdBXoX5A6QJUYOlhUkNleDo not use this test pub key in production or with sensitive card data. For a production pub key, contact ammar@ozura.com . See Vault Quick Start for full details.
2. Initialize and mount bank fields
<! DOCTYPE html >
< html >
< head >
< script type = "module" >
import { OzVault } from 'https://elements.ozura.com/oz-elements.esm.js' ;
const vault = new OzVault ( 'YOUR_VAULT_API_KEY' , {
pubKey: 'YOUR_PUB_KEY' ,
});
// Create bank elements
const accountEl = vault . createBankElement ( 'accountNumber' );
const routingEl = vault . createBankElement ( 'routingNumber' );
// Mount into your DOM
accountEl . mount ( '#account-number' );
routingEl . mount ( '#routing-number' );
// Tokenize on submit
document . getElementById ( 'submit-btn' ). addEventListener ( 'click' , async () => {
const firstName = document . getElementById ( 'first-name' ). value ;
const lastName = document . getElementById ( 'last-name' ). value ;
const { token , bank } = await vault . createBankToken ({ firstName , lastName });
// bank.last4 — last 4 digits of account number (safe to display)
// bank.routingNumber — the routing number (returned for display)
// Send token to your backend
await fetch ( '/api/ach-charge' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({ token }),
});
});
</ script >
</ head >
< body >
< input id = "first-name" placeholder = "First name" />
< input id = "last-name" placeholder = "Last name" />
< div id = "account-number" ></ div >
< div id = "routing-number" ></ div >
< button id = "submit-btn" > Submit </ button >
</ body >
</ html >
3. Process the payment on your backend
Your backend receives the token and forwards it to your ACH processor via the Proxy:
curl -X POST https://api.ozuravault.com/proxy/transaction \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_VAULT_API_KEY" \
-d '{
"token": "tok_...",
"proxy_url": "https://api.yourachprocessor.com/payments",
"request_data": {
"account_number": "${accountNumber}",
"routing_number": "${routingNumber}",
"first_name": "${first_name}",
"last_name": "${last_name}",
"amount": 5000
}
}'
Token Response
createBankToken() resolves with:
{
token : string ; // vault token — pass to your backend
bank ?: {
last4: string ; // last 4 digits of account number (safe to display)
routingNumber : string ; // routing number
};
}
Use change events to gate your submit button until both fields are complete and valid:
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 ();
});
Elements validate in real-time:
Account number — 4–17 digits; masked like a password field to prevent shoulder surfing
Routing number — Exactly 9 digits, validated against the standard ABA checksum algorithm
Field Validation & Error Handling
accountEl . on ( 'change' , ({ complete , valid , error }) => {
const wrap = document . getElementById ( 'account-wrap' );
const status = document . getElementById ( 'account-error' );
wrap . classList . toggle ( 'complete' , complete && valid );
wrap . classList . toggle ( 'invalid' , ! valid && error != null );
status . textContent = error ?? '' ;
});
Error messages returned in the error field:
"Invalid account number" — fewer than 4 digits or not all digits
"Invalid routing number" — not 9 digits or fails ABA checksum
React Integration
There are no pre-built React bank field components. Use the vanilla OzVault API inside a useEffect to create and mount bank elements manually:
import { useEffect , useRef } from 'react' ;
import { OzVault } from '@ozura/elements' ;
export function BankForm () {
const vaultRef = useRef < OzVault | null >( null );
const accountWrapRef = useRef < HTMLDivElement >( null );
const routingWrapRef = useRef < HTMLDivElement >( null );
useEffect (() => {
const vault = new OzVault ( 'YOUR_VAULT_API_KEY' , { pubKey: 'YOUR_PUB_KEY' });
vaultRef . current = vault ;
const accountEl = vault . createBankElement ( 'accountNumber' );
const routingEl = vault . createBankElement ( 'routingNumber' );
if ( accountWrapRef . current ) accountEl . mount ( accountWrapRef . current );
if ( routingWrapRef . current ) routingEl . mount ( routingWrapRef . current );
return () => vault . destroy ();
}, []);
const handleSubmit = async ( firstName : string , lastName : string ) => {
if ( ! vaultRef . current ) return ;
const { token } = await vaultRef . current . createBankToken ({ firstName , lastName });
// send token to backend
};
return (
< div >
< div ref = { accountWrapRef } />
< div ref = { routingWrapRef } />
</ div >
);
}
Styling
Bank elements accept the same style config as card elements:
const style = {
base: { color: '#1a1a2e' , fontSize: '15px' , padding: '12px 14px' , backgroundColor: '#f8fafc' },
focus: { backgroundColor: '#ffffff' , caretColor: '#6366f1' },
invalid: { color: '#ef4444' },
complete: { color: '#22c55e' },
placeholder: { color: '#94a3b8' },
};
const accountEl = vault . createBankElement ( 'accountNumber' , { style });
const routingEl = vault . createBankElement ( 'routingNumber' , { style });
See the Styling guide for the full property reference.
Next Steps
Elements SDK Reference Complete API reference — all methods, options, events, and TypeScript types.
Styling & Appearance Customize fonts, colors, and states to match your brand.
Proxy Forward the bank token to your ACH processor.
API Reference — Tokenize Token response shape and all tokenize options.