How To: Link a Bank Account for ACH Checkout

Support ACH while owning your checkout experience: have the customer link a bank account once with a standalone bank link or the embeddable bank link component, then reuse the token for every later ACH checkout.

Overview

Support ACH while owning your checkout experience. An ACH charge runs against a bank account token, and Coinflow gives you two ways for a customer to link their bank account and hand you back a token you can reuse:

  1. Standalone bank link — a Coinflow-hosted page you redirect the customer to. Works everywhere, including mobile and native apps.
  2. <CoinflowBankLink> component — an embeddable component from the React SDK that keeps the customer on your page. Web only.

Either way, the customer only links a bank account once. Every later ACH checkout reuses the saved token, which you can read back from Get Customer.

<CoinflowBankLink> is web only

<CoinflowBankLink> is available in @coinflowlabs/react only. It is not available in @coinflowlabs/react-native, and it must not be embedded in a mobile app’s webview.

Bank authentication can hand the customer off to their bank’s own native app, and there is no reliable way to return them to your app afterwards — the customer gets stranded mid-flow.

Mobile and native app integrations must use the standalone bank link, opened in the system browser (Safari.app on iOS, the default browser on Android) — not an in-app browser such as SFSafariViewController.

Which flow should I use?

IntegrationUseWhy
Web checkout, React<CoinflowBankLink>Customer never leaves your page.
Web checkout, non-ReactStandalone bank linkNo SDK required — only a redirect.
iOS / Android / React Native appStandalone bank link, opened in the system browserBank authentication can hand off to a bank’s native app.
Server-driven or emailed onboardingStandalone bank linkThe link can be delivered to the customer out of band.

1

Step 1: Whitelist your callback URL

callbackUrl is where Coinflow redirects the customer once linking completes. Like every other Coinflow redirect URL, it must be whitelisted on your merchant account first — see Domain Whitelisting for Coinflow Checkout.

For a native app, whitelist the universal link or deep link that takes the customer back into your app.

Authentication is the same as Get Checkout Link: your merchant API key, plus an x-coinflow-auth-user-id header identifying the customer who is linking the account.

$curl -X POST https://api-sandbox.coinflow.cash/api/checkout/bank-link \
> -H "Authorization: YOUR_API_KEY" \
> -H "x-coinflow-auth-user-id: user123" \
> -H "Content-Type: application/json" \
> -d '{
> "email": "payer@gmail.com",
> "callbackUrl": "https://yourapp.example.com/bank-linked",
> "theme": "light"
> }'
Response
1{
2 "link": "https://sandbox.coinflow.cash/checkout-link/MERCHANT_ID?sessionKey=SESSION_KEY&bankAccountLinkRedirect=https%3A%2F%2Fyour-site.com%2Fbank-linked"
3}

Treat link as opaque: send the customer to it exactly as returned, whether you redirect to it or load it in an iframe. Its path and query parameters are an implementation detail and may change.

Build the URL from this endpoint rather than by hand. Some of the link’s parameters are compressed, and one of them decides whether the flow ends on Coinflow’s confirmation or carries on into Coinflow’s own checkout. A hand-assembled URL that gets it wrong drops your customer into a Coinflow purchase flow in the middle of your checkout.

All values above are examples. Replace YOUR_API_KEY, the customer id, the email, and the callback URL with your own. Every field in the request body is optional; send only what your integration needs.

FieldDescription
callbackUrlWhere the customer is returned once the session ends, however it ends. Carries a bankLinkStatus parameter. Must be whitelisted on your merchant account. Omit it to end on Coinflow’s confirmation instead, and read the accounts back from Get Customer.
emailPre-fills the customer’s email so they don’t have to type it.
customerInfoCustomer details you already hold, pre-filled into the flow.
themeRenders the hosted page in light or dark to match your brand.

Open the returned link. On the web you can redirect to it or embed it in an iframe from a whitelisted origin. In a native app, open it in the system browser.

Step 4: Retrieve the linked account

Coinflow returns the customer to your callbackUrl however the session ends, whether they linked an account, backed out, or could not be verified. A bankLinkStatus query parameter reports which:

https://yourapp.example.com/bank-linked?bankLinkStatus=linked
bankLinkStatusMeaning
linkedAn account was linked and is on the customer record.
canceledThe customer backed out without linking.
failedThe account could not be linked, for example because the account holder’s name could not be verified.

Reaching your callbackUrl does not mean an account was linked. Treat the session as successful only when bankLinkStatus is linked.

On linked, call Get Customer to retrieve the account. Each entry in customer.bankAccounts[] carries the token you pass to ACH checkout:

$curl -X GET https://api-sandbox.coinflow.cash/api/customer/v2 \
> -H "x-coinflow-auth-session-key: SESSION_KEY"

Reading it server-side also means a customer who closes the browser before the redirect lands still has their account saved. Most customers link one account, but the field is a list, so handle more than one.

Building on the web? <CoinflowBankLink> hands you the tokens directly through onAccountLinked, with no follow-up call. See the next section.


<CoinflowBankLink> embeds the same bank authentication flow directly in your React app, so the customer never leaves your checkout page. Review the web-only warning at the top of this page before using it.

1

Step 1: Create a session key

The component authenticates as the customer with a session key, exactly like <CoinflowPurchase>.

$curl -X GET https://api-sandbox.coinflow.cash/api/auth/session-key \
> -H "Authorization: YOUR_API_KEY" \
> -H "x-coinflow-auth-user-id: user123"

Step 2: Render the component

1import {CoinflowBankLink} from '@coinflowlabs/react';
2
3<CoinflowBankLink
4 merchantId="YOUR_MERCHANT_ID"
5 env="sandbox"
6 sessionKey="SESSION_KEY"
7 email="payer@gmail.com"
8 onAccountLinked={({type, tokens}) => {
9 console.log('Linked bank accounts', type, tokens);
10 saveBankAccountToken(tokens[0]);
11 }}
12 onAccountNotLinked={({reason}) => {
13 console.log('Bank link ended without an account', reason);
14 closeBankLinkStep();
15 }}
16/>;

merchantId, env, and sessionKey are required. The rest are optional:

PropDescription
emailPre-fills the customer’s email.
customerInfoCustomer details you already hold, pre-filled into the flow.
themeLight or dark rendering.
merchantCssCustom CSS applied inside the component, as with Coinflow’s other embeddable components.
loaderBackgroundBackground color shown while the component loads.
handleHeightChangeCalled when the embedded content’s height changes, so you can resize its container.
onAccountLinkedCalled when linking completes. See below.
onAccountNotLinkedCalled when the session ends without an account. See below.

Step 3: Handle the outcome

onAccountLinked fires with {type, tokens}, where tokens is a string[] of the newly linked bank account tokens. Persist them against the customer on your side, or re-read them from Get Customer.

onAccountNotLinked fires instead when the session ends without an account, with {type, reason}:

reasonMeaning
canceledThe customer backed out without linking.
failedThe account could not be linked, for example because the account holder’s name could not be verified.

These are the same outcomes the standalone link reports as bankLinkStatus, so the two entry points use one vocabulary.

The component stays mounted and does not navigate on either event — it is embedded in your checkout, so where the customer goes next is yours to decide. Unmount it, or move to your next step, from the handler.


Using the Token for ACH Checkout

Both flows produce the same thing: a bank account token you pass as token on ACH Checkout.

1

Step 1: Read the token back from Get Customer

$curl -X GET https://api-sandbox.coinflow.cash/api/customer/v2 \
> -H "x-coinflow-auth-session-key: SESSION_KEY"

The linked accounts come back under customer.bankAccounts[]; use the token field of the account the customer is paying with.

Step 2: Send the ACH checkout

$curl -X POST https://api-sandbox.coinflow.cash/api/checkout/ach/MERCHANT_ID \
> -H "x-coinflow-auth-session-key: SESSION_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "subtotal":{"cents":500},
> "jwtToken":"CHECKOUT_JWT_TOKEN",
> "token":"BANK_ACCOUNT_TOKEN"
> }'

See How To: Implement ACH Payments for the full ACH checkout flow, including orderType and ACH authorization records.

Linking is a one-time step per customer

Once a customer has linked a bank account, the token is saved to their Coinflow customer record. Skip the bank link entirely on later purchases and reuse the token from Get Customer — only send the customer through bank authentication again if they want to add or replace an account.


Next Steps