# Verify bank account ownership with Financial Connections Use the Ownership Match API to request match scores on ownership data. The [Ownership Match API](https://docs.stripe.com/api/financial_connections/ownership_match.md) helps you verify that your user owns a given bank account. It computes match scores by comparing Financial Connections ownership data with input owner information. ## Before you begin You must have a completed Financial Connections registration to access ownership in live mode. Visit your [Dashboard settings](https://dashboard.stripe.com/settings/financial-connections) to check the state of your registration or begin the registration process. Financial Connections test data is always available. To access Ownership Match, you must [set the API version and beta header](https://docs.stripe.com/sdks/set-version.md) to `financial_connections_ownership_match_api_preview=v1` in each API request. ## Request access to an account's ownership data [Server-side] - [Access ownership for a Financial Connections Account](https://docs.stripe.com/financial-connections/ownership.md) You must [collect a Financial Connections Account](https://docs.stripe.com/financial-connections/ownership.md#request-account-ownership) before you can access its ownership data. Specify the [data permissions](https://docs.stripe.com/financial-connections/fundamentals.md#data-permissions) you need access to with the `permissions` parameter in the API. Ownership match requires the `ownership` permission. Your user can view the set of requested data permissions in the [authentication flow](https://docs.stripe.com/financial-connections/fundamentals.md#authentication-flow). We recommend that you use [prefetch](https://docs.stripe.com/financial-connections/ownership.md#prefetch-ownership-data) to initiate the ownership refresh as soon as your user connects their account in the authentication flow. When the ownership data becomes available, we send a [financial connections webhook](https://docs.stripe.com/financial-connections/webhooks.md). ## Call the Ownership Match API [Server-side] You can pass ownership data to the API using one of the following methods: - Create a Customer object for Stripe to compare against - Collect a Financial Connections Account with an account holder of type Customer - Submit the data through the `owner_information` parameter Ownership match accepts up to four input fields, one of which must be from the following list. - Name - Email address - **Phone number**: Include the plus symbol (`+`) and country code for international - **Address**: Requires all address fields except line 2 > Including all ownership fields increases the score accuracy. For example, you can weigh each field’s match score and use it in your risk modeling. ### Create a Customer object (Recommended) We recommend that you create a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) to represent your user. Include all the data you have available that you want to match against. Stripe loads and matches the data without requiring you to handle sensitive customer data when not strictly required. For example, you can collect both a Customer and a Financial Connections Account through Stripe products, such as [ACH payments in Checkout](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md). After doing so, you can request an ownership match and make a risk decision based on the match result without seeing the customer’s ownership data, and possibly triggering PCI compliance liability. ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d "name=Jenny Rosen" \ --data-urlencode "email=jennyrosen@example.com" \ --data-urlencode "phone=+1 212-555-5555" \ -d "address[line1]=354 Oyster Point Blvd" \ -d "address[city]=South San Francisco" \ -d "address[postal_code]=94080" \ -d "address[state]=CA" \ -d "address[country]=US" ``` This returns a Customer with the ownership details ownership match can use. ```json { "id": "cus_NffrFeUfNV2Hib", "object": "customer", "created": 1651783000,"name": "Jenny Rosen", "address": { "line1": "354 Oyster Point Blvd", "line2": null, "city": "South San Francisco", "state": "CA", "postal_code": "94080", "country": "US" }, "email": "jennyrosen@example.com", "phone": "+1 212-555-5555", "livemode": false // ... } ``` Pass the Customer `id` into the API to match against the Financial Connections Account. ```curl curl https://api.stripe.com/v1/financial_connections/ownership_match \ -u "<>:" \ -H "Stripe-Version: 2026-03-25.preview; financial_connections_ownership_match_api_preview=v1" \ -d financial_connections_account=fca_1MwVK82eZvKYlo2Cjw8FMxXf \ -d type=customer \ -d customer=cus_NffrFeUfNV2Hib ``` ### Collect a Financial Connections Account with account holder of type Customer You can collect a Financial Connections Account with an associated Customer by setting `customer` to the existing Customer id, and setting its account holder to type `customer` when creating a Financial Connections Session. #### Setup Intents ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d customer=cus_NffrFeUfNV2Hib \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=ownership" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][prefetch][]=ownership" ``` #### Payment Intents ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=20000 \ -d currency=usd \ -d customer=cus_NffrFeUfNV2Hib \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=ownership" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][prefetch][]=ownership" ``` #### Sessions ```curl curl https://api.stripe.com/v1/financial_connections/sessions \ -u "<>:" \ -d "account_holder[type]=customer" \ -d "account_holder[customer]=cus_NffrFeUfNV2Hib" \ -d "permissions[]=ownership" \ -d "prefetch[]=ownership" ``` #### Checkout ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d customer=cus_NffrFeUfNV2Hib \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=ownership" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][prefetch][]=ownership" ``` #### Invoices ```curl curl https://api.stripe.com/v1/invoices \ -u "<>:" \ -d customer=cus_NffrFeUfNV2Hib \ -d "payment_settings[payment_method_types][]=us_bank_account" \ -d "payment_settings[payment_method_options][us_bank_account][financial_connections][permissions][]=ownership" \ -d "payment_settings[payment_method_options][us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_settings[payment_method_options][us_bank_account][financial_connections][prefetch][]=ownership" ``` #### Subscriptions ```curl curl https://api.stripe.com/v1/subscriptions \ -u "<>:" \ -d customer=cus_NffrFeUfNV2Hib \ -d "payment_settings[payment_method_types][]=us_bank_account" \ -d "payment_settings[payment_method_options][us_bank_account][financial_connections][permissions][]=ownership" \ -d "payment_settings[payment_method_options][us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_settings[payment_method_options][us_bank_account][financial_connections][prefetch][]=ownership" ``` This creates a Financial Connections Account with the necessary `ownership` permissions and an associated Customer. Successful prefetch or refresh of ownership returns the account, including its associated Financial Connections ownership data when `ownership` is expanded. ```json { "id": "fca_1MwVK82eZvKYlo2Cjw8FMxXf", "object": "financial_connections.account", "created": 1651783222, "account_holder": { "customer": "cus_NffrFeUfNV2Hib", "type": "customer" }, "ownership": { "id": "fcaowns_1NtI9uBHO5VeT9SUSRe21lqt", "object": "financial_connections.account_ownership", "created": 1651784999, "owners": { "object": "list", "data": [{ "name": "Jennifer Rosen", "email": "jennyrosen@test.com", "phone": null, "ownership": "fcaowns_1NtI9uBHO5VeT9SUSRe21lqt", "raw_address": "354 Oyster Point Blvd South San Francisco, CA 94080 USA", "refreshed_at": 1651784999 } ], "has_more": false, "url": "/v1/financial_connections/accounts/fca_zbyrdjTrwcYZJZc6WBs6GPid/owners?ownership=fcaowns_1NtI9uBHO5VeT9SUSRe21lqt" } }, "ownership_refresh": { "status": "succeeded", "last_attempted_at": 1651784999, "next_refresh_available_at": 1651785000 }, "permissions": ["ownership", "payment_method"], "prefetch": ["ownership"] // ... } ``` You can pass the Financial Connections Account `id` without a specified input `type` to match its Financial Connections ownership data with its associated account holder Customer data. ```curl curl https://api.stripe.com/v1/financial_connections/ownership_match \ -u "<>:" \ -H "Stripe-Version: 2026-03-25.preview; financial_connections_ownership_match_api_preview=v1" \ -d financial_connections_account=fca_1MwVK82eZvKYlo2Cjw8FMxXf ``` ### Submit the data through the owner information parameter If you choose not to collect ownership data through a Customer, you can also pass user-provided ownership data directly to the API through the `owner_information` parameter. ```json { "owner_information": { "name": "Jenny Rosen", "email": "jennyrosen@example.com", "phone": "+1 212-555-5555", "address": { "line1": "354 Oyster Point Blvd", "line2": null, "city": "South San Francisco", "state": "CA", "postal_code": "94080", "country": "US" } } } ``` Pass the owner information in the API to match against the Financial Connections Account. ```curl curl https://api.stripe.com/v1/financial_connections/ownership_match \ -u "<>:" \ -H "Stripe-Version: 2026-03-25.preview; financial_connections_ownership_match_api_preview=v1" \ -d financial_connections_account=fca_1MwVK82eZvKYlo2Cjw8FMxXf \ -d type=owner_information \ -d "owner_information[name]=Jenny Rosen" \ --data-urlencode "owner_information[email]=jennyrosen@example.com" \ --data-urlencode "owner_information[phone]=+1 212-555-5555" \ -d "owner_information[address][line1]=354 Oyster Point Blvd" \ -d "owner_information[address][line2]=" \ -d "owner_information[address][city]=South San Francisco" \ -d "owner_information[address][state]=CA" \ -d "owner_information[address][postal_code]=94080" \ -d "owner_information[address][country]=US" ``` ## Make decisions based on match results [Server-side] The Ownership Match API returns a 0-100 match score for each input field you supply. You can feed this match score into your own risk logic and modeling, as shown in the examples provided. For example, you can set score thresholds in order to proceed with a payment, or to require more verification such as identity documentation upload before proceeding. Depending on your risk tolerance and other risk signals from your customer data, you can adjust your logic to require an exact or strong match to proceed with an action, such as continuing a payment or allowing a payout to the account. ```javascript function makeRiskDecision(matchResult: Stripe.FinancialConnections.OwnershipMatch) { const nameScore = matchResult.results.name?.match_score? || 0; const addressScore = matchResult.results.address?.match_score? || 0; const emailScore = matchResult.results.email?.match_score? || 0; const phoneScore = matchResult.results.phone?.match_score? || 0; const overallScore = (nameScore + addressScore + emailScore + emailScore) / 4 if (overallScore >= 70) { proceedWithPayment(); } else if (overallScore >= 60) { stepUpVerification(); } else { cancelPayment(); } } ``` ### Examples of score interpretations #### Name, Email, Address Sample of match scores compared to the name “Jenny Jane Rosen”, the email “jennyrosen@example.com”, and the following address: ```json { "line1": "354 Oyster Point Blvd", "line2": "Fl 1", "city": "South San Francisco", "state": "CA", "postal_code": "94080", "country": "US" } ``` | Score | Interpretation | Name example | Email example | Address example | | ----- | --------------------------------------------------------------- | ------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 100 | Exact match | “Jenny Jane Rosen” | “jennyrosen@example.com” | ```json { "line1": "354 Oyster Point Blvd.", "line2": "Fl. 1", "city": "South San Francisco", "state": "CA", "postal_code": "94080", "country": "US" } ``` | | 85-99 | Very strong match, such as a few characters off | “Jneny Jane Rosen” | “jenny.rosen@example.com” | ```json { "line1": "354 Oyster Point Blvd.", "line2": null, "city": "South San Francisco", "state": "CA", "postal_code": "94080", "country": "US" } ``` | | 70-84 | Strong match, such as majority matches | “Jenny Rosen” | “jennyrosen12345@example.com” | ```json { "line1": "354 Oyster Point", "line2": "Fl. 10", "city": "San Francisco", "state": "CA", "postal_code": "94080", "country": "US" } ``` | | 60-69 | Possible match, such as partial matches or nicknames | “Jennifer Rosen” | “jennyrosen@test.com” | ```json { "line1": "354 OP Blvd.", "line2": null, "city": "South SF", "state": "CA", "postal_code": "94080", "country": "US" } ``` | | 30-59 | Weak match, such as possible household member or similar fields | “Mark Rosen” | “marksmith@example.com” | ```json { "line1": "510 Townsend St.", "line2": null, "city": "San Francisco", "state": "CA", "postal_code": "94103", "country": "US" } ``` | | 0-29 | No or unlikely match | “Mark Smith” | “marksmith@test.com” | ```json { "line1": "1 University Ave.", "line2": "Fl. 10", "city": "Toronto", "state": "ON", "postal_code": "M5J 2P1", "country": "CA" } ``` | #### Phone Sample of phone match scores compared to the phone number “+1 212-555-5555”. > The phone sample interpretation score ranges are broader, because there are fewer granular variations in phone numbers. | Score | Interpretation | Examples | | ----- | ------------------------------------------------------- | -------------------------------- | | 100 | Exact match | “+12125555555”, “(212) 555-5555” | | 70-99 | Possible match, such as a digit off or a missing number | “212 555 5559” “212 555 555” | | 50-69 | Weak match, such as all the same except area code | “347 555 5555” | | 20-49 | Unlikely match, such as only the same area code | “212 999 9999” | | 0-19 | No match | “347 999 9999” | ### Sample response The Ownership Match API also returns the matched owner information and ownership id, as shown in the following sample API response: ```json { "id": "fcom_1NtI9uBHO5VeT9SUKLJU5suZ", "object": "financial_connections.ownership_match", "created": 1745858181, "financial_connections_account": "fca_1MwVK82eZvKYlo2Cjw8FMxXf", "type": "customer", "owner_information": { "name": "Jenny Rosen", "address": { "line1": "354 Oyster Point Blvd", "line2": null, "city": "South San Francisco", "state": "CA", "postal_code": "94080", "country": "US" }, "email": "jennyrosen@example.com", "phone": "+1 212-555-5555" }, "customer": "cus_NffrFeUfNV2Hib", "ownership": "fcaowns_1NtI9uBHO5VeT9SUSRe21lqt", "results": { "name": { "match_score": 85, "missing_data": false }, "address": { "match_score": 100, "missing_data": false }, "email": { "match_score": 65, "missing_data": false }, "phone": { "match_score": null, "missing_data": true } } } ```