Bank-to-bank payments
This section provides step-by-step examples (or *recipes*) showing how to accept bank-to-bank payments.
When to Use
- For low fee payments — customers connect their bank once, then you charge via the ChargX API.
- Lower fees than card payments; funds typically settle same-day or next-day.
Overview
The bank-to-bank flow has four steps:
- Create link token — Your backend calls the API to get a
link_token. - Customer connects bank — Your frontend opens a Link UI with that token; the customer selects and connects their bank.
- Exchange public token — When Link finishes, you receive a
public_token. Your backend exchanges it for abankToken. - Create transaction — Your backend charges the customer’s bank account using
bankToken(and optionally the originallinkTokenfor customer linking).
All three API calls are documented in the Bank-to-bank section of the API reference.
Steps
1. Create link token
Before showing the bank-connection UI, call Create link token with your app name, redirect URL, and at least one of customer email or phone.
Example (fetch):
const response = await fetch("https://api.chargx.io/v1/bank-to-bank/create_link_token", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": "pk_your_publishable_key",
},
body: JSON.stringify({
clientName: "Your Store Name",
redirectUri: window.location.href, // or your success/callback URL
custEmail: "customer@example.com",
custFirstName: "Jane",
custLastName: "Doe",
themeColor: "0066CC", // optional 6-char HEX
}),
});
const data = await response.json();
if (!response.ok) throw new Error(data?.message ?? data?.error ?? "Failed to create link token");
const linkToken = data.link_token; // use in step 2 (and optionally in step 4)Store link_token for the next step and, if you want to associate the payment with a customer, pass it again when calling Bank-to-bank transact in step 4.
2. Open Link UI so the customer can connect their bank
Load the Link UI script, then initialize and open the grid with the link_token from step 1. Use the sandbox script for testing and the production script for live payments.
Script URLs:
- Sandbox:
https://cabbagepay.com/js/sandbox/cabbage.js - Production:
https://cabbagepay.com/js/production/cabbage.js
Example (React):
// Load script once (e.g. in useEffect)
const script = document.createElement("script");
script.src = isProduction
? "https://cabbagepay.com/js/production/cabbage.js"
: "https://cabbagepay.com/js/sandbox/cabbage.js";
script.async = true;
document.body.appendChild(script);
// When user clicks “Pay with bank” (after you have linkToken from step 1):
window.cabbage.initializeGrid(linkToken);
window.cabbage.openGrid(linkToken);The customer completes the flow in the Link UI modal. When they finish, the lib sends a result via window.postMessage.
3. Handle success and exchange public token
Listen for message events from the Link UI iframe. On data.message === "success", read data.public_token and call Exchange public token to get a bankToken.
Example:
window.addEventListener("message", async (event) => {
const data = typeof event.data === "string" ? JSON.parse(event.data) : event.data;
if (!data?.message) return;
if (data.message === "success") {
const publicToken = data.public_token;
if (!publicToken) {
console.error("Bank connection did not return a token");
return;
}
window.cabbage?.closeGrid?.();
const exchangeRes = await fetch("https://api.chargx.io/v1/bank-to-bank/public_token_exchange", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": "pk_your_publishable_key",
},
body: JSON.stringify({ publicToken }),
});
const exchangeData = await exchangeRes.json();
if (!exchangeRes.ok || !exchangeData.bankToken) {
throw new Error(exchangeData?.message ?? "Failed to complete bank connection");
}
const bankToken = exchangeData.bankToken;
// Optional: exchangeData.bankName, exchangeData.bankAccountLastFour
// Proceed to step 4 with bankToken (and optionally linkToken from step 1)
}
if (data.message === "terminated") {
// User closed or cancelled the bank connection
}
});4. Create the bank-to-bank transaction
Use the bankToken from step 3 (and optionally the linkToken from step 1 for customer linking) to call Bank-to-bank transact.
Example:
const orderId = "order-123-from-your-system"; // your own order/invoice id
const amount = 99.99; // in your store’s default currency; discount may be applied by ChargX
const transactRes = await fetch("https://api.chargx.io/v1/bank-to-bank/transact", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": "pk_your_publishable_key",
},
body: JSON.stringify({
bankToken,
amount,
orderId,
linkToken: linkToken ?? undefined, // optional; use if you want to link to a customer
}),
});
const transactData = await transactRes.json();
if (!transactRes.ok) {
throw new Error(transactData?.message ?? transactData?.error ?? "Payment failed");
}
// Success: use transactData.result.orderId, transactData.result.orderDisplayId, etc.
const completedOrderId = transactData.result?.orderId ?? orderId;Testing
Use the sandbox Link UI script and your ChargX test publishable key so that no real bank accounts or money are involved. In sandbox, you can complete the Link flow with test credentials:
During the account linking process, select any of the following test financial institutions:
- FinBank Profiles - A
- FinBank Profiles - B
Use any of the following credentials to log into the bank:
- profile_03/profile_03 - to test successful linking and payments up to $4999
- profile_04/profile_04 - to test successful linking and insufficient funds
Going live
When you are ready for production:
- Use the production Link UI script:
https://cabbagepay.com/js/production/cabbage.js. - Use your ChargX live publishable key and ensure your ChargX account is enabled for bank-to-bank in production.
- Ensure
redirectUriin the create-link-token request is a valid, HTTPS URL that your app controls (e.g. your checkout or success page).