Skip to content
Create account or Sign in
The Stripe Docs logo
/
Ask AI
Create accountSign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
OverviewAccept a paymentUpgrade your integration
Online payments
OverviewFind your use case
Use Payment Links
Use a prebuilt checkout page
Build a custom integration with Elements
Build an in-app integration
Use Managed PaymentsRecurring payments
In-person payments
Terminal
Payment methods
Add payment methods
Manage payment methods
Faster checkout with Link
Payment operations
Analytics
Balances and settlement time
Compliance and security
Currencies
Declines
Disputes
Fraud prevention
Radar fraud protection
Payouts
ReceiptsRefunds and cancellations
Advanced integrations
Custom payment flows
Flexible acquiring
Multiprocessor orchestration
Beyond payments
Incorporate your company
Crypto
Agentic commerce
Financial Connections
    Overview
    Get started
    Use cases
    Fundamentals
    Testing
    Supported institutions
    Collect accounts for data
    ACH Direct Debit payments
    Connect payouts
    Other data-powered products
    Access account data
    Balances
    Ownership
    Transactions
    Ownership match
    Manage accounts
    Relink an account
    Tokenized account numbers
    Disconnections
    Webhooks
Climate
Verify identities
United States
English (United States)
HomePaymentsFinancial Connections

Relink data access to a Financial Connections account with your user’s permissionPrivate preview

Learn how to reestablish data access on inactive accounts with your user’s permission.

Your end user’s previously linked Financial Connections account might become inactive for a variety of reasons, including:

  • The OAuth token provided to Stripe by their financial institution expires after a set period of time or because of inactivity.
  • The financial institution has changed their multi-factor authentication requirements.
  • The account becomes locked by their financial institution due to suspicious activity.
  • They close their account at their financial institution.
  • They change their username or password.
  • They revoke access to sharing data with you or Stripe.

New account data isn’t accessible on inactive accounts. In rare cases, new account data is permanently inaccessible–for example, when an end user closes the account at their financial institution. For all other cases, they must re-authenticate to consent to sharing new account data with you.

The Financial Connections API allows you to repair the data connection of previously linked Financial Connections accounts (with your user’s permission) with a streamlined authentication flow that directs users straight to the institution of their previously linked account.

To know when a user must relink an account, you must use a preview API Version such as 2026-01-28.preview in all of your requests and webhook endpoints as indicated in the code snippets below.

Understand when an account becomes inactive
Server-side

You’re notified when a previously linked Financial Connections account becomes inactive with the financial_connections.account.deactivated webhook. If the account’s authorization is inactive, then the inactive subhash on the status_details hash on the Authorization object shows a relink_required action if it’s possible to relink an inactive authorization. For example, you might have a webhook handler like the one below to process webhook events.

Python
No results
import stripe import requests as r from requests.auth import HTTPBasicAuth stripe.api_version = '2026-01-28.preview' # If you are testing your webhook locally with the Stripe CLI you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' @app.route('/webhook', methods=['POST']) def webhook(): event = None payload = request.data sig_header = request.headers["STRIPE_SIGNATURE"] try: event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret) except ValueError as e: # Invalid payload raise e except stripe.error.SignatureVerificationError as e: # Invalid signature raise e if event["type"] == "financial_connections.account.deactivated": account = event["data"]["object"] authorization_response = r.get("https://api.stripe.com/v1/financial_connections/authorizations/" + account["authorization"], headers={"Stripe-Version": stripe.api_version}, auth=HTTPBasicAuth(SECRET_KEY, '')) authorization = authorization_response.json() if authorization["status"] == 'inactive' and authorization["status_details"]["inactive"]["action"] == 'relink_required': prompt_user_to_relink(authorization) else: # No action to be taken. return jsonify(success=True)

Additionally, you can retrieve the status of an account by retrieving the account using the account ID.

Command Line
curl https://api.stripe.com/v1/financial_connections/accounts/:id \ -u
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:
\ -X "GET" \ -H "Stripe-Version: 2026-01-28.preview"
{ "id": "fca_1LDYuMGxLVUXRs6HW0lrat9T", "object": "financial_connections.account", //..., "authorization": "fcauth_1LDYuMGxLVUXRs6HW0lrat9T", "status": "inactive" }

You can then retrieve the authorization of the account using the authorization ID.

Command Line
curl https://api.stripe.com/v1/financial_connections/authorizations/:id \ -u
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:
\ -X "GET" \ -H "Stripe-Version: 2026-01-28.preview"
{ "id": "fcauth_1LDYuMGxLVUXRs6HW0lrat9T", "object": "financial_connections.authorization", //..., "status": "inactive", "status_details": { "inactive": { "action": "relink_required" } } }

The authorization.status_details.inactive.action is none when an inactive account can’t be relinked for data access. In this case, redirect the end user to the usual authentication flow to select an institution and connect an account from scratch.

{ "id": "fcauth_1LDYuMGxLVUXRs6HW0lrat9T", "object": "financial_connections.authorization", //..., "status": "inactive", "status_details": { "inactive": { "action": "none" } } }

In some cases, the Authorization of an account might be active, but the account itself is inactive. This might happen, for instance, if the account was closed at the institution. In these cases, the inactive account can’t be relinked for data access. Likewise in this case, redirect the end user to the usual authentication flow to select an institution and connect an account from scratch.

Retrieve the authorization to relink from an inactive Financial Connections account
Server-side

To reestablish data access on an inactive account, retrieve the ID of the account’s authorization from the account object.

{ "id": "fca_1LDYuMGxLVUXRs6HW0lrat9T", "object": "financial_connections.account", //..., "authorization": "fcauth_1LDYuMGxLVUXRs6HW0lrat9T", "status": "inactive" }

You have two options to repair data access on a Financial Connections account, which depend on whether you want to repair an account previously linked to accept ACH Direct Debit payments with Stripe, or some other purpose.

Before you can regain data access from a user’s bank account with Financial Connections, your user must re-authenticate their account with the authentication flow. They begin the authentication flow when they want to relink their account to your site or application. Insert a button or link on your site or in your application, which allows a user to re-link their account—for example, your button might say “Re-link your bank account”.

When they see the authentication flow, your end user is prompted to authenticate access to their account at the relevant financial institution. Unlike the authentication flow where your user first links a new account, your end user won’t need to choose their financial institution from the bank picker.

OptionalRepair data access on a Financial Connections account to accept ACH Direct Debit payments

Create a Financial Connections session

Create a Financial Connections Session and specify the following:

  1. Set account_holder[customer] to the customer id.
  2. Set the data permissions parameter to include payment_method, and any data you want to retrieve on the account. The permissions parameter is an array containing values, which might include any of [payment_method, balances, ownership, transactions]. To protect the privacy of your user’s data, account data accessible to you is limited to the data you specified in the permissions parameter. Carefully consider the data required to fulfill your use case, and request permission to access only the data you require. When completing the authentication flow, your user sees the data you specified from the permissions parameter, and provides their consent to share this data. The following code example demonstrates how to collect balances and payment_method.
  3. Set the relink_options[authorization] to the authorization ID to target the authorization of the account that you want to repair data access for.
  4. Set filters[account_subcategories] to checking, savings.
  5. Set limits[accounts] to 1.

You can only add one debitable account to accept ACH Direct Debit payments with Stripe.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/financial_connections/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d "account_holder[type]"=customer \ -d "account_holder[customer]"=
"{{CUSTOMER_ID}}"
\ -d "filters[account_subcategories][]"=checking \ -d "filters[account_subcategories][]"=savings \ -d "limits[accounts]"=1 \ -d "permissions[]"=payment_method \ -d "permissions[]"=balances \ -d "relink_options[authorization]"=fcauth_1LDYuMGxLVUXRs6HW0lrat9T

The request returns a response similar to the following:

{ "id": "fcsess_abcd", "object": "financial_connections.session", "livemode": true, "account_holder": { "customer": "cus_NfjonN9919dELB", "type": "customer" }, "accounts": [], "client_secret": "fcsess_client_secret_UsESkKYzeiRcivgDJZfxZRFh", "filters": { "account_subcategories": ["checking", "savings"] }, "limits": { "accounts": 1 }, "permissions": [ "payment_method", "balances" ], "relink_options": { "authorization": "fcauth_1LDYuMGxLVUXRs6HW0lrat9T" } }

Relink a Financial Connections account

Use the returned client_secret with Stripe.js to allow your user to relink their accounts. A client_secret allows client-side Stripe SDKs to make changes to the Financial Connections Session. Don’t store it, log it, embed it in URLs, or expose it to anyone other than your end user. Make sure that you have TLS enabled on any page that includes the client secret.

Use stripe.collectFinancialConnectionsAccounts to collect an account.

// Fetch existing accounts on the authorization to determine whether the linked account is new. const existing_account_ids = await fetch_existing_accounts(); const financialConnectionsSessionResult = await stripe.collectFinancialConnectionsAccounts({ clientSecret: "fcsess_client_secret_UsESkKYzeiRcivgDJZfxZRFh" });

Stripe.js loads the authentication flow, the client-side Stripe.js UI that helps your users see and consent to share the data you requested to access from the permissions parameter, and re-link their financial accounts to you and Stripe.

The authentication flow might look like the following:

Relink Flow

The return value of stripe.collectFinancialConnectionsAccounts is a Promise. When the user completes the authentication flow, the Promise resolves with an object that contains the list of relinked accounts:

stripe.collectFinancialConnectionsAccounts(clientSecret) .then(({financialConnectionsSession, error}) => { if (error) { // The session failed for some reason. console.error(error.message); } else if (financialConnectionsSession.accounts.length > 0) { // User has authorized some account on the authorization. const is_new = !existing_account_ids.includes(financialConnectionsSession.accounts[0].id); // The user has connected a new account on the authorization. if (is_new) { // You must surface the mandate for new accounts to process ACH payments. return surface_mandate(); } else { // User has reauthorized an existing payment account. reload_account(financialConnectionsSession.accounts[0].id); return display_success(); } } else if (accounts.length == 0) { // The session failed to connect an account. } });

If your user has linked an account for data sharing, the length of accounts is > 0.

Within the OAuth flows of your end users’ financial institution, it’s possible for them to select a different account than the one initially linked. The is_new field will include the new account ID if your user has linked a different account than they initially linked. Follow the steps to convert the newly created Financial Connections account into a Payment Method.

If the user has no debitable accounts, length of accounts is 0.

Relinking debitable accounts with tokenized account numbers

Because certain banks use tokenized account numbers (TANs) instead of raw account numbers, relinking an account updates the associated Payment Method data. If your user relinks a Chase or PNC account, the underlying payment method’s account number is automatically updated.

OptionalRepair data access on a Financial Connections account for all other use cases

Create a Session

Create a Financial Connections Session and specify the following:

  1. Set account_holder[customer] to the customer id.
  2. Set the data permissions parameter to include payment_method, and any data you want to retrieve on the account. The permissions parameter is an array containing values, which might include any of [payment_method, balances, ownership, transactions]. To protect the privacy of your user’s data, account data accessible to you is limited to the data you specified in the permissions parameter. Carefully consider the data required to fulfill your use case, and request permission to access only the data you require. When completing the authentication flow, your user sees the data you specified from the permissions parameter, and provides their consent to share this data. The following code example demonstrates how to collect balances and payment_method.
  3. Set the relink_options[authorization] to the authorization ID to target the authorization of the account that you want to repair data access for.
Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/financial_connections/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d "account_holder[type]"=customer \ -d "account_holder[customer]"=
"{{CUSTOMER_ID}}"
\ -d "permissions[]"=payment_method \ -d "permissions[]"=balances \ -d "relink_options[authorization]"=fcauth_1LDYuMGxLVUXRs6HW0lrat9T

The request returns a response similar to the following:

{ "id": "fcsess_abcd", "object": "financial_connections.session", "livemode": true, "account_holder": { "customer": "cus_NfjonN9919dELB", "type": "customer" }, "accounts": [], "client_secret": "fcsess_client_secret_UsESkKYzeiRcivgDJZfxZRFh", "permissions": [ "payment_method", "balances" ], "relink_options": { "authorization": "fcauth_1LDYuMGxLVUXRs6HW0lrat9T" } }

Relink a Financial Connections account

Use the returned client_secret with Stripe.js to allow your user to relink their accounts. A client_secret allows client-side Stripe SDKs to make changes to the Financial Connections Session. Don’t store it, log it, embed it in URLs, or expose it to anyone other than your end user. Make sure that you have TLS enabled on any page that includes the client secret.

Use stripe.collectFinancialConnectionsAccounts to collect an account.

// Fetch existing accounts on the authorization to determine whether the linked account is new. const existing_account_ids = await fetch_existing_accounts(); const financialConnectionsSessionResult = await stripe.collectFinancialConnectionsAccounts({ clientSecret: "fcsess_client_secret_UsESkKYzeiRcivgDJZfxZRFh" });

The return value of stripe.collectFinancialConnectionsAccounts is a Promise. When the user completes the authentication flow, the Promise resolves with an object that contains the list of relinked accounts:

stripe.collectFinancialConnectionsAccounts(client_secret).then(({session, error}) => { if (error) { // The session failed for some reason. console.error(error.message); } else if (session.accounts.length > 0) { // User has reauthorized existing Financial Connections accounts. reload_accounts(session.accounts); } else if (accounts.length == 0) { // The session failed to connect an account. } });

If your user has linked an account for data sharing, the length of accounts is > 0.

Within the OAuth flows of your end users’ financial institution it’s possible for them to select a different account than the one they initially linked.

Retrieve data on a Financial Connections account
Server-side

After your user has successfully completed the authentication flow, access or refresh the account data you specified in the permissions parameter of the Financial Connections Session.

To protect the privacy of your user’s data, account data accessible to you is limited to the data you specified in the permissions parameter.

Follow the guides for balances, ownership and transactions to start retrieving account data.

Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc