Skip to content

Financial Connections Fresh

Access your users' bank account data with their consent. Collect verified bank account information and retrieve balances, transactions, and ownership data.

How it works

  1. Your user initiates the bank account linking flow on your client
  2. Your server creates a Financial Connections Session
  3. You return the session's client_secret to the client
  4. The Stripe authentication UI launches via collectFinancialConnectionsAccounts
  5. The user consents to data sharing and links their bank account
  6. Stripe attaches FinancialConnectionsAccount objects to the session
  7. You retrieve account data from your server

Authentication flow steps

StepDescription
Give consentUser agrees to share requested data
Select institutionUser selects from 5,000+ supported banks
Log into bankUser authenticates via OAuth or non-OAuth flow
Select accountsUser selects which accounts to link
SuccessAuthentication complete

Supports web, iOS, Android, and mobile web views.

Create a Financial Connections Session

bash
curl https://api.stripe.com/v1/financial_connections/sessions \
  -u "sk_test_YOUR_KEY:" \
  -d "account_holder[type]=customer" \
  -d "account_holder[customer]={{CUSTOMER_ID}}" \
  -d "permissions[]=payment_method" \
  -d "permissions[]=balances"

Node.js:

javascript
const stripe = require('stripe')('sk_test_YOUR_KEY');

const session = await stripe.financialConnections.sessions.create({
  account_holder: {
    type: 'customer',
    customer: 'cus_CUSTOMER_ID',
  },
  permissions: ['payment_method', 'balances'],
});

// Return session.client_secret to the frontend

Launch the authentication flow (client-side)

javascript
const stripe = Stripe('pk_test_YOUR_PUBLISHABLE_KEY');

const { financialConnectionsSession, error } = await stripe.collectFinancialConnectionsAccounts({
  clientSecret: session.client_secret,
});

if (error) {
  console.error(error.message);
} else {
  const accounts = financialConnectionsSession.accounts;
  // accounts is an array of linked FinancialConnectionsAccount objects
}

Return user optimization

For return users who have previously linked accounts, create a Customer with their email before launching the flow. Stripe's Link integration allows users to reuse saved bank accounts across Stripe businesses in fewer steps:

bash
curl https://api.stripe.com/v1/customers \
  -u "sk_test_YOUR_KEY:" \
  -d email={{CUSTOMER_EMAIL}}

Pass the customer ID in the account_holder when creating the session.

Data permissions

PermissionData availableUse cases
payment_methodTokenized account and routing numberACH payments, payouts
ownershipAccount owner names and mailing addressesFraud prevention, KYC
balancesCurrent and available balanceLending, financial management
transactionsPending and posted transactionsPFM apps, lending underwriting

Request only the permissions you need. Users can see which data types you've requested and must explicitly consent to each.

After collecting an account you always receive (without special permissions):

  • Last four digits of account number
  • Account category (checking, savings)
  • Account nickname (if available)

Account numbers are tokenized by default. Full account numbers for off-Stripe ACH processing are available only to businesses that meet Stripe's risk and eligibility criteria.

Retrieve account data

After the authentication flow, retrieve data from your server:

bash
# List accounts attached to a session
curl https://api.stripe.com/v1/financial_connections/sessions/{{SESSION_ID}} \
  -u "sk_test_YOUR_KEY:" \
  -d "expand[]=accounts"

# Retrieve balances for a specific account
curl https://api.stripe.com/v1/financial_connections/accounts/{{ACCOUNT_ID}}/refresh \
  -u "sk_test_YOUR_KEY:" \
  -d "features[]=balances"

curl https://api.stripe.com/v1/financial_connections/accounts/{{ACCOUNT_ID}} \
  -u "sk_test_YOUR_KEY:" \
  -d "expand[]=balance"

OAuth vs non-OAuth authentication

Stripe defaults to OAuth (bank-hosted) authentication when available:

MethodDescription
OAuthUser goes to bank's site/app, grants permission, bank redirects back. No credentials shared with Stripe.
Non-OAuthUser provides credentials directly to Stripe or a trusted partner. Used when OAuth is unavailable at the institution.

Your integration doesn't need to treat OAuth and non-OAuth accounts differently.

FinancialConnectionsAccount object

FieldDescription
idAccount ID (fca_...)
categorycash, investment, credit, other
subcategorychecking, savings, mortgage, credit_card, etc.
statusactive, inactive, disconnected
balanceCurrent and available balance (if balances permission granted)
ownershipOwner names and addresses (if ownership permission granted)
last4Last 4 digits of account number
institution_nameName of the financial institution

Payments integration

For ACH payments, Financial Connections is the recommended way to collect and verify bank account details. Integrate with Payment Intents or Setup Intents:

javascript
const paymentMethod = await stripe.paymentMethods.create({
  type: 'us_bank_account',
  us_bank_account: {
    financial_connections_account: 'fca_ACCOUNT_ID',
  },
});

Or use the payment_method token returned from the authentication flow directly in your PaymentIntent.

Microdeposits fallback

For payments integrations, configure microdeposit fallback for users who can't complete instant verification:

javascript
const setupIntent = await stripe.setupIntents.create({
  payment_method_types: ['us_bank_account'],
  payment_method_options: {
    us_bank_account: {
      financial_connections: {
        permissions: ['payment_method'],
      },
      verification_method: 'microdeposits', // fallback
    },
  },
});

Stripe API Reference - Self-contained docs reference, refreshed 2026-05-18