ChargX Documentation

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:

  1. Create link token — Your backend calls the API to get a link_token.
  2. Customer connects bank — Your frontend opens a Link UI with that token; the customer selects and connects their bank.
  3. Exchange public token — When Link finishes, you receive a public_token. Your backend exchanges it for a bankToken.
  4. Create transaction — Your backend charges the customer’s bank account using bankToken (and optionally the original linkToken for customer linking).

All three API calls are documented in the Bank-to-bank section of the API reference.

Steps

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.

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:

  1. profile_03/profile_03 - to test successful linking and payments up to $4999
  2. profile_04/profile_04 - to test successful linking and insufficient funds

Going live

When you are ready for production:

  1. Use the production Link UI script: https://cabbagepay.com/js/production/cabbage.js.
  2. Use your ChargX live publishable key and ensure your ChargX account is enabled for bank-to-bank in production.
  3. Ensure redirectUri in the create-link-token request is a valid, HTTPS URL that your app controls (e.g. your checkout or success page).