# Upcoming requirements updates Learn about the changes to required verification information and how this impacts your integration with Stripe. The requirement updates in this guide refer to properties in the Accounts v1 API. You can see the corresponding Accounts v2 API properties in [Required verification information](https://docs.stripe.com/connect/required-verification-information.md) by selecting `v2` in the **Accounts API** dropdown and the desired update in the **Requirement update** dropdown. Payments regulations help prevent crimes such as money laundering, fraud, and tax evasion. Financial regulators around the world enforce [Know Your Customer (KYC) requirements](https://support.stripe.com/questions/know-your-customer) to make sure that Stripe collects, verifies, and maintains identity information from certain types of businesses and from individuals who ultimately own, control, or direct them. These requirements are frequently updated by financial service regulators, card networks, and other financial institutions. This guide provides an overview of the upcoming changes, and highlights the most significant changes. For the exhaustive list of requirements, refer to [Required verification information](https://docs.stripe.com/connect/required-verification-information.md). If you use an API-based flow to onboard your connected accounts, you must update your integration to handle all requirement changes. Learn more about [Connect onboarding options](https://docs.stripe.com/connect/onboarding.md) and [migrating your API-based onboarding and remediation flows to Stripe-hosted or embedded flows](https://docs.stripe.com/connect/migrate-from-api-onboarding.md). #### Program - Europe *Last updated: February 23, 2026* ## Understand the changes to verification requirements To align with regulations from the UK Financial Conduct Authority (FCA) and the Central Bank of Ireland (CBI), Stripe is updating our verification requirements for Know Your Customer (KYC) and ultimate beneficial owners (UBO) and directors. If your connected accounts operate in any of the listed countries, you might need to update your onboarding flow. Failure to make required updates will disrupt your connected accounts’ access to payments and financial services. To learn more about what’s changing and why, see the [new compliance requirements support article](https://support.stripe.com/questions/europe-verification-requirement-updates-for-connected-accounts). The upcoming changes affect connected accounts in the following countries: - AT - BE - BG - CH - CY - CZ - DE - DK - EE - ES - FI - FR - GB - GI - GR - HR - HU - IE - IS - IT - LI - LT - LU - LV - MT - NL - NO - PL - PT - RO - SE - SI - SK > #### Ongoing updates > > Stripe will continue updating the API to support collecting these requirements through April 1, 2026. ## Choose an integration approach Stripe recommends using Stripe-hosted or Embedded onboarding to collect business and identity verification requirements. These options require fewer resources to implement and maintain than using API onboarding. The following table describes the major differences: - [Stripe-hosted onboarding](https://docs.stripe.com/connect/hosted-onboarding.md): (Recommended) Send accounts to a Stripe-hosted flow to submit required information. - [Embedded onboarding](https://docs.stripe.com/connect/embedded-onboarding.md): (Recommended) Embed Stripe-provided onboarding components that let accounts submit information directly to Stripe from within your app. - [API onboarding](https://docs.stripe.com/connect/api-onboarding.md): Build and manage a custom onboarding flow using Stripe APIs. | | **Stripe-hosted onboarding** | **Embedded onboarding** | **API onboarding** | | --- | --- | --- | --- | | Best for | Platforms that want Stripe to handle onboarding | Platforms that want a branded, in-app onboarding flow | Platforms that need full control and can build and maintain it | | Initial implementation effort | 3–4 engineering weeks | 3–4 engineering weeks | 30–40 engineering weeks | | Ongoing effort to address requirement updates | Handled automatically by Stripe | Handled automatically by Stripe | Requires proactive monitoring for upcoming changes, plus engineering resources to update the onboarding flow for each change | | Customization | Stripe-hosted interface with platform branding | Highly themeable component that accounts access through the platform app | Platform designs, builds, and maintains the interface | | Effort to support additional countries | Handled automatically by Stripe | Handled automatically by Stripe | Requires engineering resources to update the onboarding flow for each additional country | Learn more about [Connect onboarding options](https://docs.stripe.com/connect/onboarding.md) and [migrating your API-based onboarding and remediation flows to Stripe-hosted or embedded flows](https://docs.stripe.com/connect/migrate-from-api-onboarding.md). The [changes you make to your onboarding flow](https://docs.stripe.com/connect/handle-verification-updates.md#collect-future-requirements) depend on your onboarding configuration. In addition to updating your onboarding flow, update your internal and external documentation as needed, and prepare your support teams to answer questions about the updates. If you use Stripe-hosted or Embedded onboarding, then you don’t need to update your integration to prepare for these requirement updates. However, you can communicate to your connected accounts that Stripe might request new or updated identity information when requirements change. ## API integration overview If you choose not to migrate to Stripe-hosted or Embedded onboarding, then you need to address the following updates: - [Know Your Customer (KYC) verification](https://docs.stripe.com/connect/upcoming-requirements-updates.md#know-your-customer-\(kyc\)-verification) - [Ultimate beneficial owner (UBO) and director relationship verification](https://docs.stripe.com/connect/upcoming-requirements-updates.md#ubo-director-verification) - [Netherlands business registration (KvK) requirements](https://docs.stripe.com/connect/upcoming-requirements-updates.md#netherlands-business-registration-requirements) - [New error codes](https://docs.stripe.com/connect/upcoming-requirements-updates.md#new-error-codes) ## Update timeline The following timeline explains the key milestones for these changes. Make sure to update and test your integration early to avoid any issues when the new requirements take effect. | Date | Milestone | Description | | --- | --- | --- | | October 2025 | Start integration planning | Initial API updates are available. Review this guide and the changes to start planning your integration updates. | | March 2026 | Review impacted accounts and test your integration updates | Stripe provides an estimated count of your impacted connected accounts. Start testing your updated onboarding flow. | | March – April 2026 | `future_requirements` rollout begins (API onboarding) | For platforms using API onboarding, Stripe starts adding the new requirements to `future_requirements` for both new and existing accounts. | | April 1, 2026 | New requirements start for platforms that only have connected accounts with business type `individual` | Make sure that your updated onboarding flow is ready to collect the new requirements. You need to have your updated flow working by April 1, when Stripe begins rolling out the new requirements. All of the new requirements will become active by the end of April. | | May 1, 2026 | New requirements start for platforms that have connected accounts with business type `company`, including platforms that also have `individual` connected accounts | Make sure that your updated onboarding flow is ready to collect the new requirements. You need to have your updated flow working for all connected accounts by May 1, when Stripe begins rolling out the new requirements. All of the new requirements will become active by the end of May. | | June 2026 – August 2026 | New requirements become currently due for existing accounts | The new requirements roll out to existing connected accounts during this period. Use your updated onboarding flow to collect them as needed. | | July – October 2026 | Due dates for new requirements | To avoid restrictions, the updated requirements for each account must be verified by that account’s due date. | ## Know your customer (KYC) verification Stripe is strengthening our identity verification process, which might require some of your connected accounts to provide additional information. We’re also adding more options to the API for verifying information. The following entities must provide verifiable KYC information: - Legal entity (for individuals and sole proprietor entities); - Account representative - UBOs (for accounts deemed high risk by the Stripe risk model) ### Additional verification methods Use the following optional methods in addition to standard keyed-in information to maximize verification success rates: - [Stripe Identity](https://docs.stripe.com/connect/upcoming-requirements-updates.md#stripe-identity): (Recommended) Use selfie and document capture for accounts that fail automatic verification. - [National ID verification](https://docs.stripe.com/connect/upcoming-requirements-updates.md#national-id-verification): Collect a national ID number up front to increase first-pass verification rates. - [Upload additional documents](https://support.stripe.com/questions/documents-for-identity-and-home-address-verification): Submit supporting identity or address documents for manual review. ### Stripe Identity (Recommended) You can attempt to verify connected accounts that fail their automatic verification by using [Stripe Identity](https://stripe.com/identity). Identity works by capturing a selfie and an [ID document](https://docs.stripe.com/acceptable-verification-documents.md). Most [European countries](https://docs.stripe.com/identity/use-cases.md) support Stripe Identity, and success rates vary by country. Create an Identity [verification session](https://docs.stripe.com/api/identity/verification_sessions.md?api-version=preview) and use the [related_person](https://docs.stripe.com/api/identity/verification_sessions/object.md?api-version=preview#identity_verification_session_object-related_person) parameter to submit `document` and `proof_of_liveness` requirements for the person. You can check the results using the API or the Dashboard. ### National ID verification In the [countries affected by this update](https://docs.stripe.com/connect/upcoming-requirements-updates.md#affected-countries), you can improve verification of a connected account representative by providing their national ID number in addition to their name, birthdate, address, and nationality. Verification currently supports only the following national ID numbers. | Country | National ID type | | --- | --- | | Denmark | Central Person Register (CPR) | | Italy | Codice Fiscale (Fiscal Code) | | Poland | PESEL number | | Spain | Documento Nacional de Identidad (DNI) | | Sweden | Personnummer (Personal Identity Number) | Countries not affected by this update, such as the US, don’t support National ID number verification. For example, you can provide the ID number for a Spanish citizen acting as a representative for a connected account in Austria, which is in the EU. However, you can’t provide the ID number for a Spanish citizen acting as a representative for a connected account in the US. > #### National ID availability > > You can start collecting national ID numbers for your connected accounts when the updated requirements become future requirements. In the meantime, the integration is available for your sandbox accounts as a preview feature. ### Implement national ID verification using the API The following example demonstrates onboarding a new connected account with the updated requirements. > The differences below only impact the v1 Accounts API, not v2. #### Step 1: Create a connected account for testing (Public preview) After future requirements roll out, create connected accounts as usual. Until then, create new connected accounts in a [sandbox](https://docs.stripe.com/sandboxes.md) to enable the new KYC behavior. Trigger this behavior by changing two parts of your account creation call: 1. Add the header `experimental_onboarding_preview=v2`. 2. Submit `capabilities[card_payments][preview]=true`. After you create the account, you see a new requirement string `representative.nationality`. This indicates you can create an account representative and pass nationality. ```shell // Creating a connected account in Spain > curl https://api.stripe.com/v1/accounts \ -u sk_test_123 \ -H "Stripe-Version: 2025-08-27.basil;experimental_onboarding_preview=v2" \ -d 'type'='custom' \ -d 'country'='ES' \ -d 'capabilities[card_payments][requested]'='true' \ -d 'capabilities[card_payments][preview]'='true' \ -d 'capabilities[transfers][requested]'='true' { "id": "acct_1Nv0FGQ9RKHgCVdB", ... "requirements": { "past_due": [ ... "representative.nationality", ... ] } ... } ``` #### Step 2: Create an account representative After you create the connected account, create an account representative. ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB/persons \ -u sk_test_123: \ -d first_name=John \ -d last_name=Doe { "id": "person_1N9XNb2eZvKYlo2CjPX7xF6B", ... } ``` #### Step 3: Submit nationality After you create an account representative, `nationality` appears in `past_due`. Collect this field so Stripe can determine if the representative is eligible for `id_number` collection. ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB -u sk_test_123: { ... "requirements": { "past_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.dob.year", ...other person requirements... "person_1N9XNb2eZvKYlo2CjPX7xF6B.nationality" ] } ... } ``` After you collect nationality, if the person is in an eligible country you see their ID number as an alternative requirement in the `alternatives` array. Each entry in the `alternatives` array represents an alternate resolution path for a standard requirement. You can fulfill an alternative requirement instead of the original requirement, but you don’t have to fulfill both. In this example, `alternatives` contains `id_number` as an alternative for the past due `dob.year` requirement. That means you can provide the person’s national ID number instead of their birth year. If you provide their birth year, you don’t have to provide their ID number. ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB/persons/person_1N9XNb2eZvKYlo2CjPX7xF6B \ -u sk_test_123: \ -d nationality=ES > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB -u sk_test_123: { "requirements": { "past_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.dob.year", ...other person fields... ], "alternatives": [ { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.dob.year", ...other person fields... ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.id_number" ] } ] } } ``` #### Step 4: Collect remaining account representative fields Collect additional person attributes, including a national ID number, to start programmatic KYC verification. ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB/persons/person_1N9XNb2eZvKYlo2CjPX7xF6B \ -u sk_test_123: \ -d 'id_number'='74362315-A' \ ...other person fields... ``` #### Step 5: Keyed-in fields go into pending verification After you provide keyed-in data, fields appear in `pending_verification` in a new way: - Keyed-in fields go into `pending_verification` rather than `verification.document` and `verification.additional_document`. This indicates the keyed-in fields are being verified. - The `id_number` requirement can go into `pending_verification` if provided, even if it appears only in `alternative_fields_due` and never in `past_due` or `currently_due`. ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB/ -u sk_test_123: { "requirements": { "pending_verification": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.city", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.line1", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.postal_code", "person_1N9XNb2eZvKYlo2CjPX7xF6B.dob.day", "person_1N9XNb2eZvKYlo2CjPX7xF6B.dob.month", "person_1N9XNb2eZvKYlo2CjPX7xF6B.dob.year", "person_1N9XNb2eZvKYlo2CjPX7xF6B.first_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.id_number", "person_1N9XNb2eZvKYlo2CjPX7xF6B.last_name" ] } } ``` #### Step 6: Handle verification errors In many cases, after fields enter `pending_verification`, the representative passes KYC and the process completes. If verification fails, Stripe returns additional information to help you guide the next steps. There are two important changes. **Multiple alternatives** In the requirements hash you’ll see multiple alternatives. Each of these represents a path forward for your users. For example, if the name and date of birth match but the name and address don’t, your connected account has several ways to resolve the issue: 1. They can check the information they’ve entered for name and address and re-enter those fields to correct any errors. 2. They can check the information they entered for dob, name, address and id_number and re-key correct information. 3. They can upload a document that matches their name and address 4. They can complete Stripe Identity These four paths appear as `past_due` fields and `alternatives`: ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB -u sk_test_123: { "requirements": { // 1. They can check the information they've entered for dob, name, and address, and re-enter the correct information. "past_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.first_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.last_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.*" ], "alternatives": [ // 2. They can check the information they entered for dob, name, address and id_number and re-key correct information. { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.first_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.last_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.*" ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.id_number" ] }, // 3. They can upload document that matches their name and address { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.first_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.last_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.*" ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.verification.additional_document" ] }, // 4. They can complete Stripe Identity { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.first_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.last_name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address.*" ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.proof_of_liveness" ] } ] } } ``` **Errors on keyed-in fields** Previously, if a verification error occurred while processing keyed-in fields, document fields went to `past_due` and errors appeared on them. Going forward, keyed-in fields return to `past_due`. Fields like `id_number` remain in `alternative_fields_due`. For example, if name, date of birth, and address are originally `past_due`, and after submission name and date of birth match while name and address don’t, then name and address return to `past_due` while date of birth is removed. In this situation, errors appear on fields in `past_due` and `alternative_fields_due`. ```shell > curl https://api.stripe.com/v1/accounts/acct_1Nv0FGQ9RKHgCVdB -u sk_test_123: { "requirements": { "past_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address" ], "alternatives": [ { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address" ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.id_number" ] }, { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address" ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.proof_of_liveness" ] }, { "original_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.name", "person_1N9XNb2eZvKYlo2CjPX7xF6B.address" ], "alternative_fields_due": [ "person_1N9XNb2eZvKYlo2CjPX7xF6B.verification.additional_document" ] } ], "errors": [ { "code": "verification_failed_keyed_identity", "reason": "Identity information could not be verified.", "requirement": "person_1N9XNb2eZvKYlo2CjPX7xF6B.name" }, { "code": "verification_failed_keyed_identity", "reason": "Identity information could not be verified.", "requirement": "person_1N9XNb2eZvKYlo2CjPX7xF6B.address" }, { "code": "verification_failed_keyed_identity", "reason": "Identity information could not be verified.", "requirement": "person_1N9XNb2eZvKYlo2CjPX7xF6B.id_number" } ] } } ``` ### High risk accounts Stripe’s risk model requires KYC verification for UBOs only for accounts classified as high risk. For testing, append `_high_risk` to the business name to force a high-risk rating. This lets you test the full KYC verification flow for owners, including the requirements and errors your integration needs to handle. This example shows how to create a high-risk test account and add owners: ```curl // Creating a connected account in Spain curl https://api.stripe.com/v1/accounts \ -u sk_test_123: \ -H "Stripe-Version: 2025-08-27.basil;experimental_onboarding_preview=v2" \ -d 'type'='custom' \ -d 'country'='ES' \ -d 'capabilities[card_payments][requested]'='true' \ -d 'capabilities[card_payments][preview]'='true' \ -d 'capabilities[transfers][requested]'='true' { "id": "acct_123", ... "requirements": {...} ... } // Set the business name to enforce the account to be high risk curl https://api.stripe.com/v1/accounts/acct_123 \ -u sk_test_123: \ -d "business_profile[name]"="example_high_risk" ``` ```curl curl https://api.stripe.com/v1/accounts/acct_123/persons \ -u sk_test_123: \ -d first_name=Marie \ -d last_name=Dupont \ -d "dob[day]"=1 \ -d "dob[month]"=1 \ -d "dob[year]"=1901 \ -d "relationship[owner]=true" \ -d "address[line1]"="address_no_match" \ -d "address[city]"="Madrid" \ -d "address[postal_code]"="28001" { "id": "person_123", ... } ``` ```curl curl https://api.stripe.com/v1/accounts/acct_123 \ -u sk_test_123: \ -d "company[owners_provided]"="true" ``` After Stripe runs KYC verification on the owner, the account requirements reflect the result. When the owner’s name matches but their address doesn’t (triggered by using the `address_no_match` test address), the requirements include `verification_failed_keyed_identity` errors on the owner’s fields: ```json { "requirements": { "past_due": [ "people.person_123.address.city", "people.person_123.address.line1", "people.person_123.address.postal_code", "people.person_123.first_name", "people.person_123.last_name" ], "errors": [ { "code": "verification_failed_keyed_identity", "requirement": "people.person_123.address.city" }, { "code": "verification_failed_keyed_identity", "requirement": "people.person_123.address.line1" }, { "code": "verification_failed_keyed_identity", "requirement": "people.person_123.address.postal_code" }, { "code": "verification_failed_keyed_identity", "requirement": "people.person_123.first_name" }, { "code": "verification_failed_keyed_identity", "requirement": "people.person_123.last_name" } ], "alternatives": [ { "original_fields_due": [ "people.person_123.address.city", "people.person_123.address.line1", "people.person_123.address.postal_code", "people.person_123.first_name", "people.person_123.last_name" ], "alternative_fields_due": [ "people.person_123.verification.additional_document" ] }, { "original_fields_due": [ "people.person_123.address.city", "people.person_123.address.line1", "people.person_123.address.postal_code", "people.person_123.first_name", "people.person_123.last_name" ], "alternative_fields_due": [ "people.person_123.verification.proof_of_liveness" ] } ] } } ``` To resolve these requirements, either resubmit the owner’s identity information or fulfill one of the alternative requirements (upload an `additional_document` or complete `proof_of_liveness`). ## Relationship verification for UBOs and directors Stripe is enhancing our verification process for ultimate beneficial owners (UBOs) and directors. European regulations require verification of the relationship of UBOs and directors to the legal entity: - **UBO:** An individual who owns or controls (directly or indirectly) more than 25% of a legal entity (for example, companies, corporations, LLCs, and partnerships). - **Director:** A member of the board of directors of the business, or any other senior person responsible for managing the business. (Examples include CEO, COO, President, Managing Director, Executive Director, and so on.) The following table shows the relationships that must be verified for each legal entity type: | Legal entity type | Relationships to verify | Note | | --- | --- | --- | | Company, corporation, LLC, partnership | UBOs if they exist; otherwise directors | UK only: both UBOs and directors | | Non-profit | Directors | Most non-profits don’t have UBOs | | Individual or sole proprietor | N/A | N/A | | Government entity or agency | N/A | To be exempt from providing UBO information, government entities must follow the process described in [this Support article](https://support.stripe.com/questions/business-verification-requirements-for-government-entities). | | Publicly traded company | N/A | To be exempt from providing UBO information, publicly traded companies must follow the process described in [this Support article](https://support.stripe.com/questions/business-verification-requirements-for-publicly-traded-companies). | ### Verify UBO and director information UBOs and directors must provide the following information: - Full name - Date of birth - Address - Email - Title (directors only) Stripe attempts to verify the person’s relationship by matching the following key properties of the person and the legal entity: | Entity | Key properties | | --- | --- | | Person | - First name - Last name - (If provided) ID number | | Legal entity | - Name - Address - Tax ID - VAT ID - Registration number | A successful verification might require only a subset of the properties to match. Stripe attempts to verify relationships in the following ways: | Method | Description | Sample requirements | | --- | --- | --- | | Third-party provider | If a third-party provider is available, Stripe automatically attempts to verify all relationships on the account. | - `owners.first_name` - `owners.last_name` - `company.tax_id` | | Official document | You can provide a “Proof of UBO” document for owners and a “Proof of Registration” document for directors. [Acceptable documents](https://docs.stripe.com/acceptable-verification-documents.md) vary by country. | - `owners.first_name` - `owners.last_name` - `company.name` - `company.address.line1` - `company.address.city` - `company.address.state` - `documents.proof_of_ultimate_beneficial_ownership` | | Digital attestation | You can use the following PDF templates to provide digital attestations for your relationships: - [UBO digital attestation template](https://docs.stripecdn.com/6e82842bfc01bd0b1c46d77f7d46b69673a9ca965ed2ad9ef53139f98abdbbaf.pdf) - [Director digital attestation template](https://docs.stripecdn.com/715ffef45157ff700bc368a4011659ee23bc8ba3c68746c5c15948a6eee1591f.pdf) | - `owners.id_number` - `company.tax_id` - `documents.proof_of_ultimate_beneficial_ownership` - `documents.proof_of_ultimate_beneficial_ownership.signer` | ### Identify relationship verification requirements using the API When you retrieve an `Account`’s requirements, the original and alternative verification options represent combinations of the key information and available verification methods. In most cases, there are at least three options for verifying owners or directors. The following code shows an example of a connected account with owner requirements. Particular options, and the order in which they appear, can vary between accounts. ```shell // Example with owner requirements > curl https://api.stripe.com/v1/accounts/acct_1234 \ -u sk_test_123: { "id": "acct_1234", "past_due": { // third-party provider option "currently_due": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.tax_id" ], "alternatives": [ { "original_fields_needed": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.tax_id" ], // official document option "alternative_fields_needed": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.name", "company.address.line1", "company.address.state", "company.address.city", "documents.proof_of_ultimate_beneficial_ownership.files" ], }, { "original_fields_needed": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.tax_id" ], // digital attestation option "alternative_fields_needed": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.name", "company.address.line1", "company.address.state", "company.address.city", "documents.proof_of_ultimate_beneficial_ownership.files", "documents.proof_of_ultimate_beneficial_ownership.signer" ], } ] } } ``` ### Verify directors instead of owners If a connected account is eligible to provide directors instead of owners, it includes alternative options for verifying directors. If you verify directors, you still need to attest that you provided 0 UBOs. The following example shows a connected account that’s eligible to verify directors instead of owners: ```shell // Example with owner requirements > curl https://api.stripe.com/v1/accounts/acct_1234 \ -u sk_test_123: { "id": "acct_1234", "past_due": { // third-party provider option for owners "currently_due": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.tax_id" ], "alternatives": [ ..., { "original_fields_needed": [ "owners.first_name", "owners.last_name", "company.owners_provided", "company.tax_id" ], // third-party provider option for directors "alternative_fields_needed": [ "directors.first_name", "directors.last_name", "company.directors_provided", "company.owners_provided", "company.tax_id" ], } ] } } ``` If you provide director information and attest to providing 0 UBOs, the primary requirement options still reflect owner requirements. You can provide owner information if it becomes available. The following example shows a connected account with 0 UBO attestation: ```shell // Example with owner requirements > curl https://api.stripe.com/v1/accounts/acct_1234 \ -u sk_test_123: { "id": "acct_1234", "past_due": { // third-party provider option for owners "currently_due": [ "owners.first_name", "owners.last_name", // company.owners_provided is no longer a requirement "company.tax_id" ], "alternatives": [ ..., { "original_fields_needed": [ "owners.first_name", "owners.last_name", "company.tax_id" ], // third-party provider option for directors "alternative_fields_needed": [ "directors.first_name", "directors.last_name", "company.directors_provided", "company.tax_id" ], } ] } } ``` ### Error Handling Owner and director requirement errors can include the following `code` values in addition to the common [document and detail mismatch errors](https://docs.stripe.com/error-codes.md). | Code | Description | | --- | --- | | `verification_missing_owners` | The `Account` is missing information about owners identified by a third-party provider or that appear in a document or digital attestation. | | `verification_missing_directors` | The `Account` is missing information about directors identified by a third-party provider or that appear in a document or digital attestation. | | `verification_data_not_found` (Private preview) | A third-party provider couldn’t find information about the business. | You can sometimes resolve these errors by updating the business details. However, in most cases, you need to direct the connected account to either the document upload path or the digital attestation path. When Stripe identifies missing owners or directors, in some cases a private preview API can provide data about them. The connected account can use that data to create the missing `Persons`. ### Implement digital attestation for UBO and director verification using the API The following example shows how to perform digital attestation for UBO or director verification. 1. Retrieve the account to identify which attestation documents are required. ```shell // Check for UBO attestation requirement > curl https://api.stripe.com/v1/accounts/acct_1234 \ -u sk_test_123: // Response showing UBO attestation { "id": "acct_1234", "requirements": { "past_due": [ "documents.proof_of_ultimate_beneficial_ownership.files", "documents.proof_of_ultimate_beneficial_ownership.signer", ], "errors": [] } } // Or for directors & officers requirement { "id": "acct_1234", "requirements": { "past_due": [ "documents.proof_of_registration.files", "documents.proof_of_registration.signer" ], "errors": [] } } ``` The digital attestation requirements option can appear as the primary option or as an alternative to a different option. Particular options, and the order in which they appear, can vary between accounts. 1. Generate a PDF using the template, and have an authorized person digitally sign it. 2. Upload the signed attestation document using the File API. ```shell curl -X POST https://files.stripe.com/v1/files \ -u sk_test_123: \ -F purpose=account_requirement \ -F file=@signed_attestation.pdf // Response { "id": "file_1234567890", "object": "file", "purpose": "account_requirement" } ``` 3. Submit the document with the ID of the `Person` that represents the signer. ```shell // For UBO attestation curl -X POST https://api.stripe.com/v1/accounts/acct_1234 \ -u sk_test_123: \ -d "documents[proof_of_ultimate_beneficial_ownership][files][]=file_1234567890" \ -d "documents[proof_of_ultimate_beneficial_ownership][signer][person]=person_xyz" // For D&O attestation curl -X POST https://api.stripe.com/v1/accounts/acct_1234 \ -u sk_test_123: \ -d "documents[proof_of_registration][files][]=file_1234567890" \ -d "documents[proof_of_registration][signer][person]=person_xyz" ``` ### Signer validation requirements Who can sign attestations - Account representatives - Business owners (25%+ ownership) - Directors and officers - Other authorized account members Important: The signer must be an existing person associated with the account. Only individuals with a documented relationship to the legal entity can sign attestation documents. ### Error handling Digital attestation introduces specific error scenarios you need to handle: #### Invalid signator Occurs when the signer isn’t associated with the account or lacks authority. ```shell { "requirements": { "errors": [{ "requirement": "documents.proof_of_ultimate_beneficial_ownership.files", "code": "invalid_signator", "reason": "Unauthorized attestation signer. The signer must have a documented relationship with the legal entity." }, { "requirement": "documents.proof_of_ultimate_beneficial_ownership.signer", "code": "invalid_signator", "reason": "Unauthorized attestation signer. The signer must have a documented relationship with the legal entity." }] } } ``` #### Document failed Occurs when the uploaded document is unreadable or incorrect. ```shell { "requirements": { "past_due": ["documents.proof_of_registration.files"], "errors": [{ "requirement": "documents.proof_of_registration.files", "code": "verification_document_failed_other", "reason": "Your team can contact Stripe to learn more about why identity verification failed." }] } } ``` #### Signer submitted without files API errors when submitting signer without files ```shell { "error": { "code": "invalid_signator", "message": "signer.person can only be provided when a file is also provided", "type": "invalid_request_error" } } ``` ### Next Steps 1. Update your integration to collect a signer when using attestation documents. 2. Implement error handling for new attestation-specific error codes. 3. Train your support team on the new attestation requirements. #### Prefill UBO and director information (Private preview) Optionally, you can also integrate with an API that programmatically detects and prefills UBOs or directors associated with a legal entity. The connected account can verify the relationship by confirming the detected information instead of through document upload or digital attestation. This path can increase verification rates and reduce friction, but it doesn’t work for all accounts. You still need to handle document uploads or digital attestations for accounts where Stripe can’t prefill their relationships. If you’re interested in prefill for UBO or director verification, sign up to express your interest below. ## Netherlands business registration (KvK) requirements **Effective May 14, 2026** Earlier in 2026, platforms were required to collect a KvK (Kamer van Koophandel) number, a unique 8-digit business registration number, from connected accounts in the Netherlands (NL). As part of this change, the `individual` business type was restricted with an `unsupported_business_type` error, and unincorporated entities were required to provide a KvK number via `company.tax_id`. Starting May 14, 2026, connected accounts representing individuals or unincorporated entities that don’t have access to a Stripe-hosted Dashboard are no longer required to provide a KvK number. Connected accounts representing individuals or unincorporated entities that have access to the full Stripe Dashboard or the Express Dashboard must still provide a KvK number. ### What’s changing - `business_type: "individual"` is now supported for connected accounts in the Netherlands that don’t have access to a Stripe-hosted Dashboard. The `unsupported_business_type` error no longer appears for these accounts. - `unincorporated_partnership` and `unincorporated_non_profit` business types no longer require `company.tax_id` to hold the KvK number for connected accounts that don’t have access to a Stripe-hosted Dashboard. ### What you need to do No action is required. You don’t need to make any changes to your integration. For existing connected accounts affected by this change: - Stripe automatically clears the `unsupported_business_type` error from `requirements.errors` for individual accounts. - Any capability restrictions (such as `card_payments` or `transfers`) tied to this error are automatically lifted. - Accounts representing individuals or unincorporated entities that were restricted for a missing KvK number are also automatically unrestricted. ## New error codes ### Verification error codes (Private preview) The new error code `verification_data_not_found` can appear in the `requirements.errors` array on the `Account` object. This error signals that Stripe was unable to retrieve information (such as UBO or Director/Officer data) from third-party verification providers using the connected account’s known legal entity details. That can happen for a number of reasons, but it’s often because the account entered their information incorrectly. This “data not found” error is distinct from existing verification error codes: - **`verification_missing_owners`**: Indicates that known owners are missing from the account. - **`verification_failed_keyed_match`**: Indicates a mismatch between submitted information and verification sources. ```shell // Example: verification_data_not_found error { "requirements": { "errors": [{ "requirement": "owners", "code": "verification_data_not_found", "reason": "Stripe was unable to retrieve ownership or director information from third-party providers based on the current legal entity details. Verify that the business information on the account is correct." }] } } ``` To handle this error, prompt the connected account to review and correct their legal entity information (company name, registration number, address). If they update their information, Stripe automatically attempts to verify it again. If the account information is correct, or if Stripe still can’t verify updated information, use a manual verification method such as document upload or digital attestation. ## Testing You can create test accounts to use when developing and testing your integration. Test accounts can simulate different verification outcomes, allowing you to see how the API returns requirements and errors for each case. The following examples help you prepare for the upcoming EU requirements changes. For more information about Connect testing in general, see [Testing Stripe Connect](https://docs.stripe.com/connect/testing.md). ### Create a test account Create a test `Account` by sending a POST request to the Accounts API using your [sandbox secret key](https://docs.stripe.com/keys.md). To access the new requirements before they’re released to non-test mode accounts, set a header enabling a preview version of the API, enable the experimental onboarding preview feature, and enable the preview version when requesting a capability. For example: ```shell curl https://api.stripe.com/v1/accounts \ -u sk_test_123: \ -H "Stripe-Version: 2026-01-28.preview;experimental_onboarding_preview=v2" \ -d 'type'='custom' \ -d 'country'='ES' \ -d 'capabilities[card_payments][requested]'='true' \ -d 'capabilities[card_payments][preview]'='true' \ -d 'capabilities[transfers][requested]'='true' \ -d 'capabilities[transfers][preview]'='true' ``` The examples below demonstrate how to simulate different situations by using values that trigger specific responses for test accounts. ### Test an Account belonging to an individual This example creates an account that doesn’t require relationship verification because the business entity type is `individual`. Create a test account following [the earlier instructions](https://docs.stripe.com/connect/upcoming-requirements-updates.md#create-a-test-account), then set the basic business details: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d business_type=individual \ -d "business_profile[mcc]"=5995 \ -d "business_profile[url]"="https://accessible.stripe.com" ``` The response includes the basic requirements for an individual. You can meet these requirements by creating a representative: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Marie" \ -d "last_name=Dupont" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=test@example.com" \ -d "phone=%2B35366666666" \ -d "nationality=ES" \ -d "relationship[representative]=true" ``` Specifying the DOB 1901-01-01 triggers successful identity verification in a sandbox. For other result triggers, see [Test dates of birth](https://docs.stripe.com/connect/testing.md#test-dobs). Similarly, setting the first line of the address to the string `address_full_match` triggers successful verification of the address. For other result triggers, see [Test business addresses](https://docs.stripe.com/connect/testing.md#test-validation-addresses). The response shows that the individual’s requirements have become pending. If you wait a few moments and retrieve the `Account`, you can see that those requirements have been cleared: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123 ``` The only remaining requirements are for the bank account (`external_account`) and terms of service (TOS). To clear the terms of service requirements, set the `Account`’s `tos_acceptance` hash: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "tos_acceptance[date]=1540248693" \ -d "tos_acceptance[ip]=10.0.0.1" ``` To clear the bank account requirements, create a test bank account for the `Account`. Specify [a test bank account number according to its country](https://docs.stripe.com/connect/testing.md#account-numbers): ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/external_accounts \ -u sk_test_123: \ -d "external_account[object]=bank_account" \ -d "external_account[account_number]=ES0700120345030000067890" \ -d "external_account[country]=ES" \ -d "external_account[currency]=EUR" ``` ### Test an Account belonging to a company This example creates an account that is subject to relationship verification requirements because the business entity type is `company`. > The UK requires verification of both the ultimate beneficial owners (UBOs) and the directors. If you’ll have connected accounts in the UK, make sure to test with accounts that have the country set to `GB`. Create a test account following [the earlier instructions](https://docs.stripe.com/connect/upcoming-requirements-updates.md#create-a-test-account), then set the basic business details: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d business_type=company \ -d "business_profile[mcc]"=5995 \ -d "business_profile[url]"="https://accessible.stripe.com" \ -d "company[name]=Test company" \ -d "company[phone]=628123456787" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=Madrid" \ -d "company[address][postal_code]=28009" \ -d "company[address][country]=ES" \ -d "company[tax_id]=000000000" ``` Specifying the tax ID number `000000000` triggers successful verification of the company. For other result triggers, see [Test business tax IDs](https://docs.stripe.com/connect/testing.md#test-business-tax-ids). Next, provide a representative. ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Adam" \ -d "last_name=" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=test@example.com" \ -d "phone=%2B35366666666" \ -d "nationality=ES" \ -d "relationship[representative]=true" \ -d "relationship[title]=CEO" ``` After the verification process for the representative completes, you can see the remaining requirements with a GET request: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: ``` The requirements in the `requirements.currently_due` array list the details we need about the owners on the `Account`. The `requirements.alternatives` array can include optional information that you can provide to fulfill certain requirements. For example: ```json { "alternative_fields_due": [ "company.owners_provided", "documents.proof_of_ultimate_beneficial_ownership.files", "owners.first_name", "owners.last_name" ], "original_fields_due": [ "company.owners_provided", "owners.first_name", "owners.last_name" ] } ``` You can provide the fields listed in `alternative_fields_due` as another way to fulfill the requirements in the corresponding `original_fields_due` list. In this example, `alternative_fields_due` includes the properties in `original_fields_due`, plus `documents.proof_of_ultimate_beneficial_ownership.files`. That means the original information is required, but you have the option to also provide a document proving ultimate beneficial ownership to help the verification process. To meet the owner requirements, create two persons and mark them as owners. The names in this example are hard-coded values for test accounts that use the tax ID number `000000000`. ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Marie" \ -d "last_name=Dupont" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=owner@example.com" \ -d "relationship[owner]=true" curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Louis" \ -d "last_name=Martin" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=owner@example.com" \ -d "relationship[owner]=true" ``` Indicate that you’ve created all of the `Account`’s owners by setting `company.owners_provided` to true: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "company[owners_provided]=true" ``` Completing this request removes all the owner requirements from the `Account`. ### Test fallback to document verification An `Account`’s owner requirements remain in `currently_due` (or in `pending_verification`, if verification is in progress) until verification is successful. When verification fails, one of your options is to upload a document. This example shows how to do so using the API. Create a test account following [the earlier instructions](https://docs.stripe.com/connect/upcoming-requirements-updates.md#create-a-test-account), then set the basic business details. Set the tax ID number to `222221001`, which triggers owner verification failure. For other result triggers, see [Test business tax IDs](https://docs.stripe.com/connect/testing.md#test-business-tax-ids). ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d business_type=company \ -d "business_profile[mcc]"=5995 \ -d "business_profile[url]"="https://accessible.stripe.com" \ -d "company[name]=Test company" \ -d "company[phone]=628123456787" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=Madrid" \ -d "company[address][postal_code]=28009" \ -d "company[address][country]=ES" \ -d "company[tax_id]=222221001" ``` Next, provide a representative: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Marie" \ -d "last_name=Dupont" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=test@example.com" \ -d "phone=%2B35366666666" \ -d "nationality=ES" \ -d "relationship[representative]=true" \ -d "relationship[title]=CEO" ``` Then, create an owner: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Adam" \ -d "last_name=Smith" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=owner@example.com" \ -d "relationship[owner]=true" ``` Indicate that you’re done creating owners by setting `company.owners_provided` to true: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "company[owners_provided]=true" ``` If you examine the `Account`, you can see that the owner requirements remain and the `requirements.errors` array contains an entry with a `requirement` of `owners` and a `code` of `verification_failed_other`. That means Stripe wasn’t able to verify the owners using the provided company information. > If you’re using the private preview version of the API, the error code is [verification_data_not_found](https://docs.stripe.com/changelog/clover/2025-10-29/accounts-verification-data-error.md) instead of `verification_failed_other`. If you receive this error for a real `Account`, check that you entered the details for the correct legal entity. This example assumes that the details are correct, and that you need to provide a document to verify them. For a real `Account`, [use the Files API to upload a document](https://docs.stripe.com/file-upload.md), then update the `Account` using the token returned in the response. For this example, use the test token `file_relationship_document_success`. For other result triggers, see [Test relationship document tokens](https://docs.stripe.com/connect/testing.md#test-relationship-document-tokens). ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "documents[proof_of_ultimate_beneficial_ownership][files][]"=file_relationship_document_success ``` A few moments after updating the `Account`, you can get the current requirements and see that the owner requirements have been cleared. ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: ``` ### Test a company with no applicable owners If a company has no owners with more than 25% ownership, Stripe requires the director information instead. This example demonstrates how to provide director information. Create a test account following [the earlier instructions](https://docs.stripe.com/connect/upcoming-requirements-updates.md#create-a-test-account), then set the basic business details. Set the tax ID number to `000000000`, which triggers company verification success. ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d business_type=company \ -d "business_profile[mcc]"=5995 \ -d "business_profile[url]"="https://accessible.stripe.com" \ -d "company[name]=Test company" \ -d "company[phone]=628123456787" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=Madrid" \ -d "company[address][postal_code]=28009" \ -d "company[address][country]=ES" \ -d "company[tax_id]=000000000" ``` Next, provide a representative: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Marie" \ -d "last_name=Dupont" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=test@example.com" \ -d "phone=%2B35366666666" \ -d "nationality=ES" \ -d "relationship[representative]=true" \ -d "relationship[title]=CEO" ``` To indicate that the business has no relevant owners, set `company.owners_provided` to true without creating any owners. To reuse an existing test `Account` that has owners, you can remove all the existing owners. ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "company[owners_provided]=true" ``` The `requirements.alternatives` array contains a set of director properties as an alternative to the owner properties. The process for creating a director is very similar to the process for creating an owner: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123/persons \ -u sk_test_123: \ -d "first_name=Adam" \ -d "last_name=Smith" \ -d "dob[year]=1901" \ -d "dob[month]=1" \ -d "dob[day]=1" \ -d "address[line1]=address_full_match" \ -d "address[city]=Madrid" \ -d "address[postal_code]=28009" \ -d "address[country]=ES" \ -d "email=owner@example.com" \ -d "relationship[director]=true" \ -d "relationship[title]=President" ``` Indicate that you’re done creating directors by setting `company.directors_provided` to true: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "company[directors_provided]=true" ``` To simulate a successful relationship verification, set `company.name` to the string `match_name_relationships`: ```shell curl https://api.stripe.com/v1/accounts/acct_test_123 \ -u sk_test_123: \ -d "company[name]=match_name_relationships" ``` ### Other test cases The following tests are also valuable: - A `non_profit` type entity, which requires director verification (UBO verification isn’t an option). - Meeting director verification requirements using a document. - Companies in the UK that require both UBO verification and director verification. #### Program - Brazil *Last updated: July 1, 2026* ## Understand the changes to verification requirements To align with regulations from the Brazilian Central Bank (BCB) under Circular BCB 3978/20, Stripe will update our verification requirements for Know Your Customer (KYC), Know Your Business (KYB), and ultimate beneficial owners (UBO). If your connected accounts operate in Brazil, you might need to update your onboarding and remediation flows. Failure to make required updates will disrupt your connected accounts’ access to payments and financial services. ## Choose an integration approach Stripe recommends using Stripe-hosted or Embedded onboarding to collect business and identity verification requirements. These options require fewer resources to implement and maintain than using API onboarding. The following table describes the major differences: - [Stripe-hosted onboarding](https://docs.stripe.com/connect/hosted-onboarding.md): (Recommended) Send accounts to a Stripe-hosted flow to submit required information. - [Embedded onboarding](https://docs.stripe.com/connect/embedded-onboarding.md): (Recommended) Embed Stripe-provided onboarding components that let accounts submit information directly to Stripe from within your app. - [API onboarding](https://docs.stripe.com/connect/api-onboarding.md): Build and manage a custom onboarding flow using Stripe APIs. | | **Stripe-hosted onboarding** | **Embedded onboarding** | **API onboarding** | | --- | --- | --- | --- | | Best for | Platforms that want Stripe to handle onboarding | Platforms that want a branded, in-app onboarding flow | Platforms that need full control and can build and maintain it | | Initial implementation effort | 3–4 engineering weeks | 3–4 engineering weeks | 30–40 engineering weeks | | Ongoing effort to address requirement updates | Handled automatically by Stripe | Handled automatically by Stripe | Requires proactive monitoring for upcoming changes, plus engineering resources to update the onboarding flow for each change | | Customization | Stripe-hosted interface with platform branding | Highly themeable component that accounts access through the platform app | Platform designs, builds, and maintains the interface | | Effort to support additional countries | Handled automatically by Stripe | Handled automatically by Stripe | Requires engineering resources to update the onboarding flow for each additional country | Learn more about [Connect onboarding options](https://docs.stripe.com/connect/onboarding.md) and [migrating your API-based onboarding and remediation flows to Stripe-hosted or embedded flows](https://docs.stripe.com/connect/migrate-from-api-onboarding.md). Platforms using Stripe-hosted or embedded onboarding don’t need to modify their integrations for these requirement updates—Stripe handles them automatically. Platforms using API-based onboarding must actively track requirement changes and allocate engineering resources for each update. ## API integration overview If your platform uses API-based onboarding, you need to update your integration to handle the following changes for Brazilian connected accounts: - **KYC: Individual identity verification**: Collect CPF, date of birth, address, and liveness proof for all individual accounts and business representatives. - **KYB: Legal entity identity verification**: Collect CNPJ, legal business name, and registered address for legal entities; handle programmatic verification and document fallback flows. - **Tax ID registration status**: Handle registration status for inactive or invalid CPF and CNPJ statuses. - **Proof of Authorization**: Verify that the business representative is authorized to represent the company; resolve via programmatic match or `company.representative_declaration` attestation. - **UBO and relationship verification**: Verify that owners (UBOs) and directors are listed in the CNPJ registry; resolve via programmatic name match, document upload, or the owner-to-director waterfall. - **Financial capacity**: Collect monthly income or gross revenue. - **New error codes**: Handle new verification error codes surfaced in the `requirements.errors` array. ## KYC: Individual identity verification Stripe will strengthen identity verification for individual accounts in Brazil to comply with Brazilian Central Bank (BCB) requirements. Connected accounts that are individuals and representatives of accounts that are legal entities need to be verified—they might need to provide additional information as part of onboarding. The following persons must provide verifiable KYC information: - **Business representative**: The individual who signs the Terms of Service and is legally responsible for the account. - **Owners**: The owners of legal entities (where applicable). Stripe uses a combination of keyed-in data and document review to verify identity for each person. Additionally, Brazilian regulation requires a liveness check (`proof_of_liveness`) to confirm that the person submitting the identity documents is physically present. Stripe-hosted and embedded onboarding flows handle this step automatically. If your platform uses API-based onboarding, you must redirect users to a Stripe-hosted verification step or integrate the `` embedded component to complete liveness collection. See [Handle liveness requirements](https://docs.stripe.com/connect/api-onboarding.md?accounts-namespace=v1&liveness=hosted#proof-of-liveness) for more details. **Age requirements:** The business representatives must be 18 years or older. Owners, directors, and officers must be 18 or older. New users who don’t meet these requirements won’t have capabilities enabled. Existing accounts with a business representative under 18 will be offboarded immediately when their platform is migrated. ### Required fields Brazilian individual accounts now require the following fields: | Field | Description | | --- | --- | | `person.first_name`, `person.last_name` | Full legal name. | | `person.id_number` | CPF (Brazilian individual taxpayer ID). | | `person.address.line1`, `.city`, `.postal_code`, `.country` | Brazilian residential address. All business representatives must be Brazilian residents and provide a Brazilian address. | | `person.dob.day`, `.month`, `.year` | Date of birth. | | `person.verification.proof_of_liveness` | Liveness selfie. (Stripe-hosted and embedded onboarding flows only) | | `person.verification.additional_document` | Optional document requirement when keyed-in address verification fails. | Make sure your UI collects a CPF specifically—we don’t accept other ID types (passport numbers, foreign tax IDs) for Brazilian accounts. ### Initial requirements response When a new individual account is created, the `requirements` hash will include: ```json { "currently_due": [ "person.first_name", "person.last_name", "person.id_number", "person.dob.day", "person.dob.month", "person.dob.year", "person.address.line1", "person.address.city", "person.address.state", "person.address.country", "person.verification.proof_of_liveness" ], "pending_verification": [], "alternatives": [ { "original_fields_due": ["person.address.line1", "person.address.city", "person.address.state", "person.address.country"], "alternative_fields_due": ["person.verification.additional_document"] } ], "errors": [] } ``` ### Collecting person data Use the Persons API to submit individual fields: ```shell curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}}/persons/{{PERSON_ID}} \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "first_name=Maria" \ -d "last_name=Silva" \ -d "id_number=123.456.789-09" \ -d "dob[day]=15" \ -d "dob[month]=6" \ -d "dob[year]=1985" \ -d "address[line1]=Rua das Flores, 123" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "address[country]=BR" ``` ### Error handling | Error code | Trigger | Remediation | | --- | --- | --- | | `verification_failed_id_number_inactive` | CPF found but the status is inactive (for example, suspended, canceled, deceased). | Users must resolve CPF status with the Brazilian Federal Revenue (Receita Federal). For accounts with canceled, null, or deceased CPF status, Stripe might disable their capabilities. | | `verification_failed_keyed_match` | Both programmatic lookup and manual review failed to verify the CPF. | The user re-submits CPF and ID document; account enters MVR queue. | | `verification_document_type_not_supported` | The uploaded document is the wrong type, from the wrong country, or unreadable. | User re-uploads an acceptable Brazilian government-issued ID. | ## Legal entity identity verification for KYB Stripe will update business verification requirements for legal entities in Brazil to comply with Brazilian Central Bank (BCB) AML regulations. This type of verification falls under broad category of know your business (KYB) requirements. If your connected accounts include businesses incorporated in Brazil, they might need to provide additional information during onboarding. Stripe verifies legal entities using the CNPJ (Cadastro Nacional da Pessoa Jurídica)—Brazil’s national company registration number—along with the business name and registered address. Stripe first attempts programmatic verification against the Brazilian government’s CNPJ registry. If the information entered doesn’t match, the account can resolve the requirement by uploading a company verification document (such as a CNPJ certificate from Receita Federal). In addition to identity verification, Brazilian AML regulation requires Stripe to assess a connected account’s financial capacity prior to enabling charges and payouts. All Brazilian accounts must provide their estimated monthly revenue or income before capabilities are activated. This information is for regulatory monitoring purposes only, and we don’t independently verify it at onboarding. ### Required fields The following fields are required for Brazilian legal entity accounts: | Field | Description | | --- | --- | | `company.tax_id` | CNPJ (14-digit Brazilian company registration number). | | `company.name` | Legal business name — must match CNPJ registry. | | `company.address.line1`, `.city`, `.postal_code` | Registered Brazilian business address. | | `company.verification.document` | Optional at first; required if programmatic verification fails. | | `business_profile.monthly_estimated_revenue.amount` | Monthly gross revenue in BRL. | | `business_profile.monthly_estimated_revenue.currency` | Must be `brl`. | ### Initial requirements response ```json { "currently_due": [ "company.tax_id", "company.name", "company.address.line1", "company.address.city", "company.address.postal_code", "business_profile.monthly_estimated_revenue.amount", "business_profile.monthly_estimated_revenue.currency" ], "pending_verification": [], "alternatives": [ { "original_fields_due": [ "company.tax_id", "company.name", "company.address.line1", "company.address.city", "company.address.postal_code" ], "alternative_fields_due": [ "company.tax_id", "company.name", "company.address.line1", "company.address.city", "company.address.postal_code", "company.verification.document" ] } ], "errors": [] } ``` The `alternatives` array indicates that if programmatic CNPJ verification fails, the platform can resolve it by also providing a `company.verification.document`. ### Collecting company data ```shell curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}} \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "company[tax_id]=12.345.678/0001-99" \ -d "company[name]=Empresa Exemplo Ltda" \ -d "company[address][line1]=Avenida Paulista, 1000" \ -d "company[address][city]=São Paulo" \ -d "company[address][postal_code]=01310-100" \ -d "company[address][country]=BR" \ -d "business_profile[monthly_estimated_revenue][amount]=5000000" \ -d "business_profile[monthly_estimated_revenue][currency]=brl" ``` After submitting company tax ID, name, and address, the requirements move to `pending_verification` while Stripe verifies against the CNPJ registry: ```json { "currently_due": [], "pending_verification": [ "company.tax_id", "company.name", "company.address.line1", "company.address.city", "company.address.postal_code" ], "alternatives": [], "errors": [] } ``` Wait for an `account.updated` webhook before proceeding. If verification succeeds, all fields clear from the requirements. If verification fails, see the error handling section below. ### Tax ID registration status In addition to verifying the CNPJ against business records, Stripe checks the registration status of the CNPJ (and the CPF of the business representative) against Brazilian government records. You can’t change the tax ID after you set it. | Legal entity type | Pass | Fail | Immediate offboarding required | | --- | --- | --- | --- | | Individuals (CPF) | Regular | Suspended, Pending Regularization | Canceled, Null, Deceased | | Legal entities (CNPJ) | Active (Ativa), Pending Regularization (Ativa não regular) | Suspended (Suspensa) | Dissolved (Baixada), Canceled (Baixada), Inapt (Inapta), Null (Nula), Foreign-domiciled | Accounts with a suspended CPF or CNPJ are treated as valid at onboarding but are expected to resolve their status within approximately 30 days. If unresolved, we’ll degrade payment capabilities. Accounts with offboarding-required statuses (canceled, null, deceased, dissolved, inapt) have all capabilities disabled immediately and can’t remediate through document upload. ### Financial capacity Brazilian AML regulation requires Stripe to collect a connected account’s estimated financial capacity before enabling charges and payouts. This applies to all Brazilian accounts—both individuals and legal entities. `monthly_estimated_revenue.amount` is expressed in the smallest currency unit (centavos). For example, 50,000 BRL = `5000000`. We collect the values for regulatory monitoring purposes only, and don’t independently verify them at onboarding. ### Error handling | Error code | Trigger | Remediation | | --- | --- | --- | | `verification_failed_keyed_match` | CNPJ not found, or the business name or the address didn’t match CNPJ registry. | Re-enter the correct legal name and registered address; or upload `company.verification.document`. | | `verification_failed_id_number_status_not_found` | CNPJ found but tax status couldn’t be retrieved. | Re-submit or upload a company verification document. | | `verification_failed_id_number_inactive` | CNPJ found but the status is inactive (for example, suspended, dissolved). | For suspended status, the account has a grace period to resolve with Receita Federal. For dissolved, canceled, inapt, or null statuses, the account will be offboarded—you can’t resolve this through document upload. | | `verification_document_type_not_supported` | The company document uploaded is unreadable or the wrong type. | Re-upload an acceptable company verification document. | | `verification_document_name_mismatch` | The business name in the document doesn’t match the name entered. | Re-enter the legal name exactly as it appears on the CNPJ certificate. | | `verification_document_id_number_mismatch` | The tax ID in document doesn’t match CNPJ that was entered, or the tax ID status isn’t found or is inactive. | Re-upload a current CNPJ certificate from Receita Federal. | | `verification_document_address_mismatch` | The address in the document doesn’t match the entered address. | Re-enter the address to match the registered address on the CNPJ certificate. | ## Proof of Authorization All non-`individual` accounts in Brazil require Proof of Authorization (PoA) verification. This confirms that the business representative is authorized to act on behalf of the company. Stripe first attempts programmatic verification by checking the representative’s name against the CNPJ registry. If the representative’s name matches an authorized person in the registry, verification passes automatically and no further action is needed. If the programmatic check fails, the representative must submit a `company.representative_declaration` attestation. ### Initial requirements alternative For a company `Account`, the [alternatives](https://docs.stripe.com/api/accounts/object.md#account_object-requirements-alternatives) array contains the fields required for the representative declaration attestation: ```json { "alternatives": [ { "original_fields_due": ["representative.first_name", "representative.last_name"], "alternative_fields_due": [ "company.representative_declaration.date", "company.representative_declaration.ip", "representative.first_name", "representative.last_name" ] } ] } ``` If Stripe’s initial attempt to verify `representative.first_name` and `representative.last_name` fails, then the platform or account needs to provide the date and IP address of the representative’s attestation. Their first and last names are also still required (appearing in both `original_fields_due` and `alternative_fields_due`). ### Error state when programmatic verification fails If the provided name doesn’t match the CNPJ registry, the [requirements.errors](https://docs.stripe.com/api/accounts/object.md#account_object-requirements-errors) array contains `Person`-specific requirements with `verification_failed_representative_authority` error codes. Also, the `alternatives` array is updated to reference the `Person` ID in `original_fields_due`: ```json { "errors": [ { "requirement": "people.{{PERSON_ID}}.first_name", "code": "verification_failed_representative_authority" }, { "requirement": "people.{{PERSON_ID}}.last_name", "code": "verification_failed_representative_authority" } ], "alternatives": [ { "original_fields_due": [ "company.name", "company.tax_id", "people.{{PERSON_ID}}.first_name", "people.{{PERSON_ID}}.last_name" ], "alternative_fields_due": [ "company.representative_declaration.date", "company.representative_declaration.ip" ] }, { "original_fields_due": ["company.owners_provided", "owners.first_name", "owners.last_name"], "alternative_fields_due": [ "company.directors_provided", "company.owners_provided", "directors.first_name", "directors.last_name" ] }, { "original_fields_due": ["company.owners_provided", "owners.first_name", "owners.last_name"], "alternative_fields_due": [ "company.directors_provided", "company.owners_provided", "directors.first_name", "directors.last_name", "documents.proof_of_registration.files" ] }, { "original_fields_due": ["company.owners_provided", "owners.first_name", "owners.last_name"], "alternative_fields_due": [ "company.owners_provided", "documents.proof_of_ultimate_beneficial_ownership.files", "owners.first_name", "owners.last_name" ] } ] } ``` ### Submit the representative declaration To resolve a failed programmatic PoA verification, provide the representative declaration attestation: ```shell curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}} \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "company[representative_declaration][date]={{UNIX_TIMESTAMP}}" \ -d "company[representative_declaration][ip]={{USER_IP_ADDRESS}}" \ -d "company[representative_declaration][user_agent]={{USER_AGENT}}" ``` The `date` field is a Unix timestamp representing the time the representative agreed to the declaration. The `ip` field is the IP address of the representative at that time. The `user_agent` field is optional but recommended. After the declaration is provided, the PoA errors clear and the account can proceed with remaining requirements (such as UBO verification). ### Error handling | Error code | Trigger | Remediation | | --- | --- | --- | | `verification_failed_representative_authority` | The representative’s name does not match any authorized person in the CNPJ registry. | Submit `company.representative_declaration` with `date` (Unix timestamp) and `ip` (representative’s IP address) to attest authorization. | ## UBO and relationship verification Brazilian AML regulation (Circular BCB 3978/20) requires that owners (UBOs) and directors of legal entities be identified and verified as legally listed in the CNPJ registry. ### Scope of regulation The following business types are subject to AML regulation: | Verification type | Business structures | | --- | --- | | Owner (UBO) verification | Multi-member LLC (MMLLC), private corporation, private partnership | | Director verification | Public corporation, government entity, non-profit | | Not in scope | Individuals, sole proprietorships (MEI) | ### Collect information in order Collect owner (UBO) information first. If the account has no owners, such as when all shareholders are legal entities instead of individuals, collect director information instead. This waterfall logic helps Stripe verify the account’s beneficial ownership structure in the most efficient order. ### How verification works Stripe recommends that you provide owners and directors as follows: 1. **Programmatic prefill** (Private preview): After KYB verification completes, you can get owner or director names from the prefill API. If you provide persons whose names match, verification passes via one-way matching. See [Prefill owner and director information](https://docs.stripe.com/connect/upcoming-requirements-updates.md#prefill-owner-and-director-information) to sign up. 2. **Document fallback**: If the prefilled names don’t match, upload `documents.proof_of_ultimate_beneficial_ownership` (for owners) or `documents.proof_of_registration` (for directors). 3. **Director waterfall**: If owners can’t be verified (for example, all owners are legal entities rather than individuals), resolve using `company.directors_provided` and director persons instead. ### Required Person fields | Field | Description | | --- | --- | | `person.first_name`, `person.last_name` | Full legal name (must match CNPJ registry for programmatic verification). | | `person.id_number` | CPF (Brazilian individual taxpayer ID). | | `person.dob.day`, `.month`, `.year` | Date of birth. | | `person.address.line1`, `.city`, `.state`, `.postal_code` | Brazilian residential address. | | `person.email` | Email address. | | `person.political_exposure` | Political exposure declaration (`none` or `existing`). | | `person.relationship.owner` or `person.relationship.director` | Role on the account (`owner` for UBOs, `director` for directors). | | `person.relationship.percent_ownership` | Optional; omitting treats the person as a UBO (>25% threshold). | ### Initial requirement alternatives for a company When a company account is created, the `requirements.alternatives` array includes alternatives for the three verification paths (director waterfall, director waterfall + doc, owner doc upload): ```json { "currently_due": [ "company.owners_provided", "owners.first_name", "owners.last_name", "owners.id_number", "owners.dob.day", "owners.dob.month", "owners.dob.year", "owners.address.line1", "owners.address.city", "owners.address.state", "owners.address.postal_code", "owners.email", "owners.political_exposure" ], "alternatives": [ { "original_fields_due": ["company.owners_provided", "owners.first_name", "owners.last_name"], "alternative_fields_due": [ "company.directors_provided", "company.owners_provided", "directors.first_name", "directors.last_name" ] }, { "original_fields_due": ["company.owners_provided", "owners.first_name", "owners.last_name"], "alternative_fields_due": [ "company.directors_provided", "company.owners_provided", "directors.first_name", "directors.last_name", "documents.proof_of_registration.files" ] }, { "original_fields_due": ["company.owners_provided", "owners.first_name", "owners.last_name"], "alternative_fields_due": [ "company.owners_provided", "documents.proof_of_ultimate_beneficial_ownership.files", "owners.first_name", "owners.last_name" ] } ] } ``` The three alternatives represent different ways to satisfy the owner verification requirement: - **Director waterfall**: Instead of verifying owners, provide directors (`company.directors_provided`, `directors.first_name`, `directors.last_name`). - **Director waterfall + document**: Provide directors and upload a `documents.proof_of_registration` file. - **Owner document upload**: Provide owner names and upload a `documents.proof_of_ultimate_beneficial_ownership` file. ### Prefill owner and director information (Private preview) Optionally, you can integrate with an API that programmatically detects and prefills owners or directors associated with a legal entity. The connected account can verify the relationship by confirming the detected information instead of through document upload. This path can increase verification rates and reduce friction, but it doesn’t work for all accounts. You still need to handle document uploads or the director waterfall for accounts where Stripe can’t prefill their relationships. If you’re interested in prefill for owner or director verification, sign up to express your interest below. ### Programmatic owner match Create owner persons with names matching the CNPJ registry, then confirm owners are provided. If the owner’s name matches, verification clears programmatically. You can optionally use the [prefill API](https://docs.stripe.com/connect/upcoming-requirements-updates.md#prefill-owner-and-director-information) (Private preview) to retrieve suggested names before creating persons. ```shell # Create owner with matching name curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}}/persons \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "first_name=Maria" \ -d "last_name=Santos" \ -d "id_number=123.456.789-09" \ -d "dob[day]=15" \ -d "dob[month]=6" \ -d "dob[year]=1985" \ -d "address[line1]=Rua das Flores, 123" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "email=maria@example.com" \ -d "political_exposure=none" \ -d "relationship[owner]=true" \ -d "relationship[percent_ownership]=26" # Confirm owners provided curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}} \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "company[owners_provided]=true" ``` If the owner’s name matches the registry, verification clears programmatically. ### Owner document upload If the owner’s name doesn’t match the CNPJ registry (or programmatic verification is not enabled), a `verification_missing_owners` error appears. Upload a proof of UBO document to resolve: ```shell # 1. Upload the relationship document curl https://files.stripe.com/v1/files \ -u "{{PLATFORM_SECRET_KEY}}:" \ -F "file=@/path/to/ownership_document.pdf" \ -F "purpose=account_requirement" # 2. Attach to account curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}} \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "documents[proof_of_ultimate_beneficial_ownership][files][0]={{FILE_ID}}" ``` ### Director waterfall If the owner can’t be verified (for example, all shareholders are legal entities), resolve by providing directors instead: ```shell # Create director person curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}}/persons \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "first_name=Carlos" \ -d "last_name=Oliveira" \ -d "id_number=987.654.321-00" \ -d "dob[day]=20" \ -d "dob[month]=3" \ -d "dob[year]=1978" \ -d "address[line1]=Av Brasil, 500" \ -d "address[city]=Rio de Janeiro" \ -d "address[state]=RJ" \ -d "address[postal_code]=20040-020" \ -d "email=carlos@example.com" \ -d "political_exposure=none" \ -d "relationship[director]=true" # Confirm directors and owners provided curl https://api.stripe.com/v1/accounts/{{CONNECTED_ACCOUNT_ID}} \ -u "{{PLATFORM_SECRET_KEY}}:" \ -d "company[directors_provided]=true" \ -d "company[owners_provided]=true" ``` ### Acceptable documents The acceptable ownership documents depend on whether the ownership structure is simple (all shareholders are individuals) or complex (at least one shareholder is itself a legal entity): #### Simple ownership structures Upload a *contrato social* or *estatuto social*. The document must contain the following: - Legal entity name and CNPJ - Each shareholder’s full name and CPF (or date of birth for non-residents) - Ownership percentages - Signatures - Commercial registry stamp (Junta Comercial) #### Complex ownership structures Download the Stripe letter of attestation template ([UBO template](https://docs.stripecdn.com/6e82842bfc01bd0b1c46d77f7d46b69673a9ca965ed2ad9ef53139f98abdbbaf.pdf) or [Directors template](https://docs.stripecdn.com/715ffef45157ff700bc368a4011659ee23bc8ba3c68746c5c15948a6eee1591f.pdf)), then fill it out and upload it. Companies with intermediary layers (holding companies, trusts, subsidiaries) that separate the ultimate beneficial owners from the operating entity must use this path. ### Error handling | Error code | Trigger | Remediation | | --- | --- | --- | | `verification_missing_owners` | Owner names provided do not match any owner in the CNPJ registry. | Add persons with names matching the registry, or upload `documents.proof_of_ultimate_beneficial_ownership`. | | `verification_missing_directors` | Director names provided do not match any director in the CNPJ registry. | Add persons with names matching the registry, or upload `documents.proof_of_registration`. | | `verification_data_not_found` | No owner or director data could be retrieved from the CNPJ registry for this entity. | Upload `documents.proof_of_ultimate_beneficial_ownership` (for owners) or `documents.proof_of_registration` (for directors). | | `verification_document_type_not_supported` | The uploaded relationship document is unreadable or the wrong type. | Upload an acceptable document (contrato social, estatuto social, or Stripe attestation template). | ## Testing Use [test mode](https://docs.stripe.com/connect/testing.md) to verify your integration handles all KYC/KYB states. ### Test: Successful KYC (individual) ```shell # Create test account curl https://api.stripe.com/v1/accounts \ -u "{{TEST_SECRET_KEY}}:" \ -H "Stripe-Version: 2026-03-25.dahlia;experimental_onboarding_preview=v2" \ -d "type=custom" \ -d "country=BR" \ -d "capabilities[transfers][requested]=true" # Submit person data (use test CPF: 000.000.001-91 for success) curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons/{{PERSON_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "first_name=Maria" \ -d "last_name=Silva" \ -d "id_number=000.000.001-91" \ -d "dob[day]=15" \ -d "dob[month]=6" \ -d "dob[year]=1985" \ -d "address[line1]=Rua das Flores, 123" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "address[country]=BR" ``` To complete testing for success of KYC, `proof_of_liveness` is still required. See [Handle liveness requirements](https://docs.stripe.com/connect/api-onboarding.md?accounts-namespace=v1&liveness=hosted#proof-of-liveness) for more details. ### Test: CPF inactive (`verification_document_id_number_mismatch`) ```shell curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons/{{PERSON_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "id_number=000.000.002-00" ``` Expected error in requirements: ```json { "code": "verification_document_id_number_mismatch", "reason": "", "requirement": "person.id_number" } ``` ### Test: Successful KYB (legal entity) ```shell # Create test company account curl https://api.stripe.com/v1/accounts \ -u "{{TEST_SECRET_KEY}}:" \ -H "Stripe-Version: 2026-03-25.dahlia;experimental_onboarding_preview=v2" \ -d "type=custom" \ -d "country=BR" \ -d "business_type=company" \ -d "capabilities[transfers][requested]=true" # Submit company data (use test CNPJ: 00.000.000/0001-91 for success) curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[tax_id]=00.000.000/0001-91" \ -d "company[name]=Empresa Teste Ltda" \ -d "company[address][line1]=Avenida Paulista, 1000" \ -d "company[address][city]=São Paulo" \ -d "company[address][postal_code]=01310-100" \ -d "company[address][country]=BR" \ -d "business_profile[monthly_estimated_revenue][amount]=5000000" \ -d "business_profile[monthly_estimated_revenue][currency]=brl" ``` ### Test: CNPJ keyed match failure (`verification_failed_keyed_match`) ```shell curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[tax_id]=00.000.000/0002-00" \ -d "company[name]=Wrong Name Ltda" ``` Expected errors in requirements: ```json [ { "code": "verification_failed_keyed_match", "requirement": "company.tax_id" }, { "code": "verification_failed_keyed_match", "requirement": "company.name" }, { "code": "verification_failed_keyed_match", "requirement": "company.address.line1" } ] ``` Resolve by uploading a company verification document: ```shell # 1. Upload CNPJ certificate PDF curl https://files.stripe.com/v1/files \ -u "{{TEST_SECRET_KEY}}:" \ -F "file=@/path/to/cnpj_certificate.pdf" \ -F "purpose=account_requirement" # 2. Attach to account curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[verification][document][front]={{FILE_ID}}" ``` ### Test: PoA programmatic success Use `match_representative` as the representative’s first name, with a non-magic CNPJ. The test provider returns a successful match, and no attestation is needed. ```shell # Create company account curl https://api.stripe.com/v1/accounts \ -u "{{TEST_SECRET_KEY}}:" \ -d "type=custom" \ -d "country=BR" \ -d "business_type=company" \ -d "company[structure]=private_company" \ -d "company[tax_id]=123456789" \ -d "company[name]=Empresa Teste Ltda" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=São Paulo" \ -d "company[address][state]=SP" \ -d "company[address][postal_code]=01310-100" \ -d "capabilities[card_payments][requested]=true" # Create representative with magic first_name curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons \ -u "{{TEST_SECRET_KEY}}:" \ -d "first_name=match_representative" \ -d "last_name=Silva" \ -d "id_number=000000000" \ -d "dob[day]=1" \ -d "dob[month]=1" \ -d "dob[year]=1901" \ -d "address[line1]=address_full_match" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "email=rep@example.com" \ -d "political_exposure=none" \ -d "relationship[representative]=true" \ -d "relationship[title]=CEO" ``` Expected: No `verification_failed_representative_authority` errors. PoA clears programmatically. Only UBO requirements remain. ### Test: PoA programmatic failure with attestation fallback Use `mismatch_representative` as the representative’s first name. The programmatic check fails and the person’s name fields have `verification_failed_representative_authority` errors. ```shell # Create company account curl https://api.stripe.com/v1/accounts \ -u "{{TEST_SECRET_KEY}}:" \ -d "type=custom" \ -d "country=BR" \ -d "business_type=company" \ -d "company[structure]=private_company" \ -d "company[tax_id]=000000000" \ -d "company[name]=Empresa Teste Ltda" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=São Paulo" \ -d "company[address][state]=SP" \ -d "company[address][postal_code]=01310-100" \ -d "capabilities[card_payments][requested]=true" # Create representative with mismatch magic first_name curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons \ -u "{{TEST_SECRET_KEY}}:" \ -d "first_name=mismatch_representative" \ -d "last_name=Silva" \ -d "id_number=000000000" \ -d "dob[day]=1" \ -d "dob[month]=1" \ -d "dob[year]=1901" \ -d "address[line1]=address_full_match" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "email=rep@example.com" \ -d "political_exposure=none" \ -d "relationship[representative]=true" \ -d "relationship[title]=CEO" ``` Expected errors in requirements: ```json [ { "code": "verification_data_not_found", "requirement": "directors.first_name" }, { "code": "verification_data_not_found", "requirement": "directors.last_name" }, { "code": "verification_data_not_found", "requirement": "owners.first_name" }, { "code": "verification_data_not_found", "requirement": "owners.last_name" }, { "code": "verification_failed_representative_authority", "requirement": "people.{{PERSON_ID}}.first_name" }, { "code": "verification_failed_representative_authority", "requirement": "people.{{PERSON_ID}}.last_name" } ] ``` The `verification_data_not_found` errors appear because the CNPJ registry returned no UBO data for the test CNPJ. Resolve by submitting the representative declaration: ```shell curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[representative_declaration][date]=1772226508" \ -d "company[representative_declaration][ip]=162.211.155.69" ``` After submitting, PoA errors clear and only UBO requirements remain. ### Test: Fulfill requirements using programmatic owner match Use CNPJ `222221003` to trigger the `verification_missing_owners` error. Create an owner with a name matching the CNPJ registry to resolve. You can optionally use the [prefill API](https://docs.stripe.com/connect/upcoming-requirements-updates.md#prefill-owner-and-director-information) (Private preview) to retrieve the expected names. ```shell # Create company with magic CNPJ for missing owners curl https://api.stripe.com/v1/accounts \ -u "{{TEST_SECRET_KEY}}:" \ -d "type=custom" \ -d "country=BR" \ -d "business_type=company" \ -d "company[structure]=private_company" \ -d "company[tax_id]=222221003" \ -d "company[name]=Empresa Teste Ltda" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=São Paulo" \ -d "company[address][state]=SP" \ -d "company[address][postal_code]=01310-100" \ -d "capabilities[card_payments][requested]=true" # Create owner with name matching the CNPJ registry curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons \ -u "{{TEST_SECRET_KEY}}:" \ -d "first_name=match_representative" \ -d "last_name=match_representative" \ -d "id_number=000000000" \ -d "dob[day]=1" \ -d "dob[month]=1" \ -d "dob[year]=1901" \ -d "address[line1]=address_full_match" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "email=owner@example.com" \ -d "political_exposure=none" \ -d "relationship[owner]=true" \ -d "relationship[percent_ownership]=26" # Confirm owners provided curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[owners_provided]=true" ``` Expected: After setting `owners_provided`, all owner requirements clear. No `verification_missing_owners` errors remain. ### Test: Fulfill requirements using owner document upload (`verification_missing_owners`) Use CNPJ `222221003` and create an owner with a non-matching name. After `verification_missing_owners` errors appear, upload a proof of UBO document to resolve. ```shell # Create non-matching owner curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons \ -u "{{TEST_SECRET_KEY}}:" \ -d "first_name=Carlos" \ -d "last_name=NonMatch" \ -d "id_number=000000000" \ -d "dob[day]=1" \ -d "dob[month]=1" \ -d "dob[year]=1901" \ -d "address[line1]=address_full_match" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "email=carlos@example.com" \ -d "political_exposure=none" \ -d "relationship[owner]=true" # Set owners_provided curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[owners_provided]=true" ``` Expected errors after evaluation: ```json [ { "code": "verification_missing_owners", "requirement": "owners.first_name" }, { "code": "verification_missing_owners", "requirement": "owners.last_name" } ] ``` Resolve by uploading a document: ```shell # Upload relationship document curl https://files.stripe.com/v1/files \ -u "{{TEST_SECRET_KEY}}:" \ -F "file=@/path/to/ownership_doc.pdf" \ -F "purpose=account_requirement" # Attach to account curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "documents[proof_of_ultimate_beneficial_ownership][files][0]={{FILE_ID}}" ``` ### Test: Fulfill requirements through director waterfall Use CNPJ `222221004` to trigger the director verification path. Create director persons with names matching the CNPJ registry. You can optionally use the [prefill API](https://docs.stripe.com/connect/upcoming-requirements-updates.md#prefill-owner-and-director-information) (Private preview) to retrieve the expected names. ```shell # Create company with magic CNPJ for missing directors curl https://api.stripe.com/v1/accounts \ -u "{{TEST_SECRET_KEY}}:" \ -d "type=custom" \ -d "country=BR" \ -d "business_type=company" \ -d "company[structure]=private_company" \ -d "company[tax_id]=222221004" \ -d "company[name]=Empresa Teste Ltda" \ -d "company[address][line1]=address_full_match" \ -d "company[address][city]=São Paulo" \ -d "company[address][state]=SP" \ -d "company[address][postal_code]=01310-100" \ -d "capabilities[card_payments][requested]=true" # Create director with name matching the CNPJ registry curl https://api.stripe.com/v1/accounts/{{ACCT_ID}}/persons \ -u "{{TEST_SECRET_KEY}}:" \ -d "first_name=match_representative" \ -d "last_name=match_representative" \ -d "id_number=000000000" \ -d "dob[day]=1" \ -d "dob[month]=1" \ -d "dob[year]=1901" \ -d "address[line1]=address_full_match" \ -d "address[city]=São Paulo" \ -d "address[state]=SP" \ -d "address[postal_code]=01310-100" \ -d "email=director@example.com" \ -d "political_exposure=none" \ -d "relationship[director]=true" # Confirm directors and owners provided curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "company[directors_provided]=true" \ -d "company[owners_provided]=true" ``` Expected: After setting `directors_provided` and `owners_provided`, director and owner requirements clear. ### Test: Resolve an invalid document upload (`verification_document_type_not_supported`) Upload an invalid relationship document to trigger the `verification_document_type_not_supported` error. Then upload a valid document to resolve. ```shell # Upload invalid document (use file_relationship_document_invalid magic value) curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "documents[proof_of_ultimate_beneficial_ownership][files][0]=file_relationship_document_invalid" ``` Expected errors after evaluation: ```json [ { "code": "verification_document_type_not_supported", "requirement": "documents.proof_of_ultimate_beneficial_ownership.files" }, { "code": "verification_missing_owners", "requirement": "owners.first_name" }, { "code": "verification_missing_owners", "requirement": "owners.last_name" } ] ``` The `verification_missing_owners` errors persist because uploading an invalid document doesn’t resolve the name mismatch. Resolve by uploading a valid document: ```shell curl https://api.stripe.com/v1/accounts/{{ACCT_ID}} \ -u "{{TEST_SECRET_KEY}}:" \ -d "documents[proof_of_ultimate_beneficial_ownership][files][0]=file_relationship_document_success" ``` #### Program - Singapore *Last updated: June 12, 2026* ## Understand the changes to verification requirements To align with revised Monetary Authority of Singapore (MAS) PSN01 requirements, Stripe is updating our requirements for Know Your Business (KYB) and ultimate beneficial owner (UBO) verification. If your connected accounts operate in Singapore, you might need to update your onboarding and remediation flows. Failure to make required updates will disrupt your connected accounts’ access to payments and financial services. ## Choose an integration approach Stripe recommends using Stripe-hosted or Embedded onboarding to collect business and identity verification requirements. These options require fewer resources to implement and maintain than using API onboarding. The following table describes the major differences: - [Stripe-hosted onboarding](https://docs.stripe.com/connect/hosted-onboarding.md): (Recommended) Send accounts to a Stripe-hosted flow to submit required information. - [Embedded onboarding](https://docs.stripe.com/connect/embedded-onboarding.md): (Recommended) Embed Stripe-provided onboarding components that let accounts submit information directly to Stripe from within your app. - [API onboarding](https://docs.stripe.com/connect/api-onboarding.md): Build and manage a custom onboarding flow using Stripe APIs. | | **Stripe-hosted onboarding** | **Embedded onboarding** | **API onboarding** | | --- | --- | --- | --- | | Best for | Platforms that want Stripe to handle onboarding | Platforms that want a branded, in-app onboarding flow | Platforms that need full control and can build and maintain it | | Initial implementation effort | 3–4 engineering weeks | 3–4 engineering weeks | 30–40 engineering weeks | | Ongoing effort to address requirement updates | Handled automatically by Stripe | Handled automatically by Stripe | Requires proactive monitoring for upcoming changes, plus engineering resources to update the onboarding flow for each change | | Customization | Stripe-hosted interface with platform branding | Highly themeable component that accounts access through the platform app | Platform designs, builds, and maintains the interface | | Effort to support additional countries | Handled automatically by Stripe | Handled automatically by Stripe | Requires engineering resources to update the onboarding flow for each additional country | Learn more about [Connect onboarding options](https://docs.stripe.com/connect/onboarding.md) and [migrating your API-based onboarding and remediation flows to Stripe-hosted or embedded flows](https://docs.stripe.com/connect/migrate-from-api-onboarding.md). Platforms using Stripe-hosted or embedded onboarding don’t need to modify their integrations for these requirement updates – Stripe handles them automatically. Platforms using API-based onboarding must actively track requirement changes and allocate engineering resources for each update. ## API integration overview If your platform uses API-based onboarding, update your integration to handle the following changes for Singapore connected accounts: - **KYB: Business details and legal entity verification:** Collect [business details and legal entity fields](https://docs.stripe.com/connect/upcoming-requirements-updates.md#kyb-business-details-and-legal-entity-verification), including date of incorporation, principal place of business, and place of administration. - **Registered address verification:** Handle [registered address verification](https://docs.stripe.com/connect/upcoming-requirements-updates.md#registered-address-verification) when Stripe can’t automatically verify the registered address. - **Constitution document verification:** Collect a [constitution document](https://docs.stripe.com/connect/upcoming-requirements-updates.md#constitution-document-verification) for companies and non-profits that don’t use a [Model Constitution](https://sso.agc.gov.sg/SL/CoA1967-S833-2015?DocDate=20151231). - **UBO and relationship verification:** Collect [UBO and relationship verification information](https://docs.stripe.com/connect/upcoming-requirements-updates.md#ubo-and-relationship-verification) for owners, directors, and key executives where required. Before enforcement, you can monitor [future_requirements](https://docs.stripe.com/api/accounts/object.md#account_object-future_requirements) to preview upcoming requirements. After requirements become active, monitor the account’s `requirements` hash and listen to the `account.updated` webhook to detect requirement changes. Make sure your integration is set up to [handle verification updates](https://docs.stripe.com/connect/handle-verification-updates.md) when onboarding new accounts and collecting updated information from existing accounts. ## KYB: Business details and legal entity verification Stripe is updating KYB requirements for Singapore non-[individual](https://docs.stripe.com/api/accounts/object.md#account_object-business_type) accounts. These requirements include new [company](https://docs.stripe.com/api/accounts/object.md#account_object-company) fields and verification of registered business information. ### Required fields | Field | Type | Description | | --- | --- | --- | | `company.registration_date` (New) | Object with `day`, `month`, and `year` | Date the business was incorporated. | | `company.address` | [Address](https://docs.stripe.com/api/accounts/object.md#account_object-company-address) object | Registered business address (new verification of existing requirement) | | `company.principal_place_of_business` (New) | [Address](https://docs.stripe.com/api/accounts/object.md#account_object-company-address) object | Primary location where the business conducts operations. | | `company.administrative_address` (New) | [Address](https://docs.stripe.com/api/accounts/object.md#account_object-company-address) object | Location where the business is administered. | If any of the addresses are the same, submit the same address values for each one. Don’t skip any of them. Create a Singapore company account. Use the returned account ID in the following examples. ```curl curl https://api.stripe.com/v1/accounts \ -u "<>:" \ -d country=SG \ -d type=custom \ -d business_type=company \ -d "capabilities[card_payments][requested]=true" \ -d "capabilities[transfers][requested]=true" ``` ### Initial requirements response The new account’s `requirements` hash includes entries such as: ```json { "currently_due": [ "company.registration_date.day", "company.registration_date.month", "company.registration_date.year", "company.address.line1", "company.address.postal_code", "company.principal_place_of_business.line1", "company.principal_place_of_business.postal_code", "company.administrative_address.line1", "company.administrative_address.postal_code" ] } ``` The fields in `currently_due` remain there until you provide values for them. ### Collect business details The following example shows how to submit the new requirements: ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[registration_date][day]=20" \ -d "company[registration_date][month]=3" \ -d "company[registration_date][year]=2015" \ --data-urlencode "company[address][line1]=60 Anson Road #05-01" \ -d "company[address][postal_code]=079914" \ --data-urlencode "company[principal_place_of_business][line1]=60 Anson Road #05-01" \ -d "company[principal_place_of_business][postal_code]=079914" \ --data-urlencode "company[administrative_address][line1]=1 Raffles Place #30-01" \ -d "company[administrative_address][postal_code]=048616" ``` ### Registered address verification The registered address (`company.address`) is already mandatory for Singapore accounts. This update adds verification for the registered address as part of legal entity verification. If Stripe can’t verify the account’s registered address, check the Account object’s `requirements` hash. It shows which address fields failed verification, lists `company.verification.document` as an alternative way to resolve the requirement, and includes details in the [`errors`](https://docs.stripe.com/api/accounts/object.md#account_object-requirements-errors) array: ```json { "currently_due": [ "company.address.line1", "company.address.postal_code" ], "alternatives": [ { "original_fields_due": [ "company.address.line1", "company.address.postal_code" ], "alternative_fields_due": [ "company.verification.document" ] } ], "errors": [ { "code": "verification_failed_keyed_match", "reason": "We couldn't verify the account's information.", "requirement": "company.address.line1" }, { "code": "verification_failed_keyed_match", "reason": "We couldn't verify the account's information.", "requirement": "company.address.postal_code" } ] } ``` To resolve the requirement collect an acceptable company verification document from the connected account. - For locally incorporated businesses: A [BizFile](https://www.bizfile.gov.sg/) profile from the [Accounting and Corporate Regulatory Authority (ACRA)](https://www.acra.gov.sg/). - For societies: A certificate of registration or annual return filed with the [Registry of Societies (ROS)](https://www.mha.gov.sg/what-we-do/registry-of-societies). - For [Majlis Ugama Islam Singapura (MUIS)](https://www.muis.gov.sg/) related entities: A letter from MUIS that contains the registered address. Upload company verification document. ```bash curl https://files.stripe.com/v1/files \ -u <>: \ -F "file"="@/path/to/company_verification_document.pdf" \ -F "purpose"="account_requirement" ``` Attach company verification document to account. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[verification][document][front]={{FILE_ID}}" ``` ## Constitution document verification Companies and non-profit organizations must satisfy the constitution document requirement. This requirement doesn’t apply to sole proprietorships or individuals. | Account classification | API values | Constitution document requirement | | --- | --- | --- | | Private company | `business_type=company` with `company.structure=private_company` | Required unless ACRA confirms the account uses a Model Constitution. | | Public company | `business_type=company` with `company.structure=public_company` | Required unless ACRA confirms the account uses a Model Constitution. | | Non-profit | `business_type=non_profit` | Required when returned in the account’s requirements. | | Sole proprietorship or individual | `business_type=company` with `company.structure=sole_proprietorship`, or `business_type=individual` | Not required. | If ACRA confirms that the entity has adopted a [Model Constitution](https://sso.agc.gov.sg/SL/CoA1967-S833-2015?DocDate=20151231), the constitution document requirement is automatically fulfilled and no document upload is required. Otherwise, you need to collect the document and submit it as `documents.company_memorandum_of_association.files`. Stripe reviews the document to identify any individuals who hold significant control, authority, or powers over the entity. You must add any such individuals to the account as UBOs to fulfill the requirements. | Field | Type | | --- | --- | | `documents.company_memorandum_of_association.files` (New) | File upload. | ### Initial requirements response When a constitution document is required, the account’s `requirements` hash includes: ```json { "currently_due": [ "documents.company_memorandum_of_association.files" ] } ``` ### Upload a constitution document The following example shows how to upload a custom constitution document: ```bash curl https://files.stripe.com/v1/files \ -u <>: \ -F "file"="@/path/to/constitution.pdf" \ -F "purpose"="account_requirement" ``` Attach constitution document to account. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "documents[company_memorandum_of_association][files][]={{FILE_ID}}" ``` ### Error handling Handle standard [document verification errors](https://docs.stripe.com/connect/handling-api-verification.md#handle-document-verification-problems) for constitution document uploads. ## UBO and relationship verification Singapore UBO requirements depend on the connected account’s business type. 1. Private companies must identify and add owners. If Stripe doesn’t identify any individuals who own 25% or more of the company, Stripe treats the company’s directors as UBOs. 2. Non-profits must identify and add directors and key executives. 3. Some entities can qualify for a UBO exemption, such as eligible financial institutions or entities that are 75% or more owned by qualifying holding companies. ### Required fields | Person API field | Description | | --- | --- | | `person.first_name`, `person.last_name` | Legal name. | | `person.full_name_aliases` | [Name aliases](https://docs.stripe.com/api/persons/object.md#person_object-full_name_aliases). | | `person.id_number` | National identification number (NRIC or FIN for Singapore residents). | | `person.nationality` (New) | Two-letter country code ([ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)). | | `person.dob` (New) | [Date of birth](https://docs.stripe.com/api/persons/object.md#person_object-dob). | | `person.address` (New) | [Residential address](https://docs.stripe.com/api/persons/object.md#person_object-address). | For UBO owners and directors, Stripe verifies legal name and ID number. Stripe only collects aliases, nationality, date of birth, and residential address for SG ORR. These fields don’t trigger separate verification. The required person fields use role-prefixed paths in the account’s `requirements` hash: ```json { "currently_due": [ "company.owners_provided", "company.directors_provided", "owners.first_name", "owners.last_name", "owners.id_number", "owners.full_name_aliases", "owners.nationality", "owners.dob.day", "owners.dob.month", "owners.dob.year", "owners.address.line1", "owners.address.postal_code", "directors.first_name", "directors.last_name", "directors.id_number", "directors.full_name_aliases", "directors.nationality", "directors.dob.day", "directors.dob.month", "directors.dob.year", "directors.address.line1", "directors.address.postal_code" ] } ``` Depending on the account state, some fields might already be populated or prefilled. Submit the fields that appear in the account’s `requirements.currently_due`, `requirements.eventually_due`, or `requirements.past_due` arrays. ### Submit UBO fields If Stripe has already created or prefilled the [Person](https://docs.stripe.com/api/persons/object.md), update that [Person](https://docs.stripe.com/api/persons/object.md) with the missing fields. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}}/persons/{{PERSON_ID}} \ -u "<>:" \ -d nationality=SG \ -d "dob[day]=15" \ -d "dob[month]=6" \ -d "dob[year]=1985" \ --data-urlencode "address[line1]=10 Bayfront Avenue #01-01" \ -d "address[city]=Singapore" \ -d "address[postal_code]=018956" \ -d "address[country]=SG" ``` If you create a new UBO [Person](https://docs.stripe.com/api/persons/object.md), include the person’s relationship, legal name, ID number, aliases, nationality, date of birth, and residential address. #### Owners as UBOs for companies For private companies, Stripe attempts to identify individuals who own 25% or more of the company from government records. When Stripe identifies owners, list the account’s persons to find the prefilled owner records. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}}/persons \ -u "<>:" ``` Update each owner with any missing fields returned in the account’s requirements. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}}/persons/{{PERSON_ID}} \ -u "<>:" \ -d nationality=SG \ -d "dob[day]=15" \ -d "dob[month]=6" \ -d "dob[year]=1985" \ --data-urlencode "address[line1]=10 Bayfront Avenue #01-01" \ -d "address[city]=Singapore" \ -d "address[postal_code]=018956" \ -d "address[country]=SG" ``` After all required owners are added or updated, set `company.owners_provided=true` if that field appears in the account’s requirements. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[owners_provided]=true" ``` #### Directors as UBOs for companies If Stripe doesn’t identify any individuals who own 25% or more of a private company, Stripe can treat directors listed on government records as UBOs. In this case, the account’s requirements include director-prefixed fields. ```json { "currently_due": [ "company.directors_provided", "directors.first_name", "directors.last_name", "directors.id_number", "directors.full_name_aliases", "directors.nationality", "directors.dob.day", "directors.dob.month", "directors.dob.year", "directors.address.line1", "directors.address.postal_code" ] } ``` Create a [Person](https://docs.stripe.com/api/persons/object.md) with the director relationship for each required director. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}}/persons \ -u "<>:" \ -d "relationship[director]=true" \ -d "first_name=Kai Ming" \ -d last_name=Wong \ -d id_number=S0000001A \ -d nationality=SG \ -d "dob[day]=20" \ -d "dob[month]=3" \ -d "dob[year]=1980" \ --data-urlencode "address[line1]=1 Raffles Place #30-01" \ -d "address[city]=Singapore" \ -d "address[postal_code]=048616" \ -d "address[country]=SG" ``` After all required directors are added, set `company.directors_provided=true`. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[directors_provided]=true" ``` Stripe can also require a directorship declaration to confirm that the list of directors on the account is current and complete. The requirement can appear when Stripe needs to verify the directors on the account against government records, including when it identifies missing directors: ```json { "currently_due": [ "company.directorship_declaration.date", "company.directorship_declaration.ip" ] } ``` If these fields appear in the account’s requirements, submit the directorship declaration. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[directorship_declaration][date]=1719360000" \ -d "company[directorship_declaration][ip]=203.0.113.42" ``` #### Directors and key executives as UBOs for non-profits For non-profits, collect UBO information for directors and key executives, not owners. For charities registered in Singapore, Stripe attempts to identify these people from available government records. For other non-profits, your platform must add each required director or key executive as a [Person](https://docs.stripe.com/api/persons/object.md) on the account. The account’s requirements use director-prefixed paths: ```json { "currently_due": [ "company.directors_provided", "directors.first_name", "directors.last_name", "directors.id_number", "directors.full_name_aliases", "directors.nationality", "directors.dob.day", "directors.dob.month", "directors.dob.year", "directors.address.line1", "directors.address.postal_code" ] } ``` Create a [Person](https://docs.stripe.com/api/persons/object.md) with the director relationship for each director or key executive. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}}/persons \ -u "<>:" \ -d "relationship[director]=true" \ -d first_name=Aisha \ -d "last_name=Binte Hassan" \ -d id_number=S0000002B \ -d nationality=SG \ -d "dob[day]=10" \ -d "dob[month]=9" \ -d "dob[year]=1975" \ --data-urlencode "address[line1]=5 Shenton Way #10-01" \ -d "address[city]=Singapore" \ -d "address[postal_code]=068808" \ -d "address[country]=SG" ``` After all required directors or key executives are added, set `company.directors_provided=true`. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[directors_provided]=true" ``` ### Proof of UBO document as fallback If Stripe can’t determine the account’s UBOs, the account must provide a [proof of ultimate beneficial ownership document](https://docs.stripe.com/acceptable-verification-documents.md?country=SG&document-type=relationship#select-a-country-to-view-its-requirements). The document must identify the accounts’ UBOs and include proof of ownership for any holding companies that own 25% or more of the account. The account’s requirements include: ```json { "currently_due": [ "documents.proof_of_ultimate_beneficial_ownership.files" ] } ``` Upload the [proof of ultimate beneficial ownership document](https://docs.stripe.com/acceptable-verification-documents.md?country=SG&document-type=relationship#select-a-country-to-view-its-requirements). ```bash curl https://files.stripe.com/v1/files \ -u <>: \ -F "file"="@/path/to/proof_of_ubo.pdf" \ -F "purpose"="account_requirement" ``` Attach the document to the account. ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "documents[proof_of_ultimate_beneficial_ownership][files][]={{FILE_ID}}" ``` After the document is reviewed, add any UBOs identified in the document as [Persons](https://docs.stripe.com/api/persons/object.md) on the account. Use the relationship returned by the account requirements, such as `relationship.owner=true` or `relationship.director=true`, and complete any returned owner or director fields. ### UBO exemption In some cases, a business entity can qualify for an ownership exemption. If the account is eligible, provide `company.ownership_exemption_reason`. | Exemption reason | When to use it | | --- | --- | | `qualifies_as_financial_institution` | Use when the entity appears on the [MAS Financial Institution Directory](https://eservices.mas.gov.sg/fid). | | `qualified_entity_exceeds_ownership_threshold` | Use when the entity is 75% or more owned by qualifying holding companies, such as Singapore government entities, investment or finance firms, or public companies. | ```curl curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \ -u "<>:" \ -d "company[ownership_exemption_reason]=qualifies_as_financial_institution" ``` If Stripe rejects the exemption reason, the account receives a `verification_rejected_ownership_exemption_reason` error. The account must then provide the required ownership information or submit a [proof of ultimate beneficial ownership document](https://docs.stripe.com/acceptable-verification-documents.md?country=SG&document-type=relationship). ### Error handling | Error code | When it can appear | Remediation | | --- | --- | --- | | `verification_missing_owners` | Stripe identified missing beneficial owners. | Add the required owners, or provide a [proof of ultimate beneficial ownership document](https://docs.stripe.com/acceptable-verification-documents.md?country=SG&document-type=relationship) when requested. | | `verification_missing_directors` | Stripe identified missing directors. | Add the required directors and set `company.directors_provided=true`. | | `verification_document_directors_mismatch` | Director information in a submitted document doesn’t match the account information. | Add or update the required directors, or provide corrected supporting documentation. | | `verification_requires_additional_proof_of_registration` | Stripe needs more information about the account’s ownership structure. | Provide a [proof of ultimate beneficial ownership document](https://docs.stripe.com/acceptable-verification-documents.md?country=SG&document-type=relationship) with the required ownership information. | | `verification_rejected_ownership_exemption_reason` | Stripe rejected the submitted ownership exemption reason. | Add the required UBOs or provide the required [proof of ultimate beneficial ownership document](https://docs.stripe.com/acceptable-verification-documents.md?country=SG&document-type=relationship). | ## Getting help - For questions about these requirement changes, contact [Stripe Support](https://support.stripe.com). - For API integration questions, see the [Connect documentation](https://docs.stripe.com/connect.md). - To monitor your accounts’ compliance status, use the [Accounts to Review](https://dashboard.stripe.com/connect/accounts/overview) page in your Dashboard. #### Program - US *Last updated: September 23, 2025* ## What’s changing - **Required information collected from connected accounts:** We’re updating the information we require from sole proprietorships, non-profits and single-member LLCs and simplifying how we obtain legal guardian consent for accounts opened by minors. In addition, an email for the account representative is now required for all legal entity types, and a change for government entities and public companies. - **How we verify business information and provide new detailed verification responses:** We’re updating our criteria for valid business information and introducing new verification error codes when we unable to accept or verify information provided. - **Threshold at which we verify tax identification numbers (TINs):** For Custom and Express connected accounts, we’re lowering the payments volume threshold at which we verify TINs to align with current federal tax reporting thresholds. - **How we prefill statement descriptors and statement descriptor prefixes:** If a statement descriptor isn’t provided, the prefill logic has changed to use either the business profile name, the business URL, or the legal entity name of the connected account. These changes will affect all users with a requested [card_payments](https://docs.stripe.com/api/accounts/object.md#account_object-capabilities-card_payments) capability in the US. ## Required information collected from connected accounts New information collected and new fields added to the API: - Businesses that are [company.structure](https://docs.stripe.com/api/accounts/create.md#create_account-company-structure) of `sole_proprietorship` and `single_member_llc`, must provide their business address (“company address”). In the event that the business address is the same as the representative’s personal address, your connected accounts can provide the same values for both. - Legal entities that are [company.structure](https://docs.stripe.com/api/accounts/create.md#create_account-company-structure) of `government_instrumentality`, `tax_exempt_government_instrumentality`, `governmental_unit`, `public_company`, `public_corporation`, and `public_partnership` must provide an email for the account representative. This requirement now applies to all legal entity types. - To simplify how we obtain a legal guardian’s consent for accounts opened by minors, the [Persons API](https://docs.stripe.com/api/persons.md) has been updated with a new relationship type of `legal_guardian` as well as an `additional_tos_acceptances` field to record the legal guardian’s agreement to the Stripe Terms of Service. If the account representative’s date of birth indicates the individual is a minor, then an account requirement is triggered to add a `legal_guardian` before the account can be activated. ## How we verify business information and provide new detailed verification responses ### Updates to the information we already collect We’ll request the following information from your connected accounts: | Field | Updated requirements | Additional considerations | | --- | --- | --- | | SSN or ITIN collected from US-resident Representatives (Reps) | Last four digits required at onboarding for all account types (including Custom and Express connected accounts) | This is the current behavior for Standard connected accounts. | | SSN or ITIN collected from US-resident Owners | Last four digits required once payments volume exceeds 500K USD for all account types (including Custom and Express connected accounts) | See *SSN Full 9 Digit Note* below | | National ID or verification document collected from non-US-resident Representatives | National ID or verification document at onboarding for all account types (including Custom and Express connected accounts) | Only applies to non-US-resident Reps | | National ID or verification document collected from non-US-resident Owners | National ID or verification document once payments volume exceeds 500K USD for all account types (including Custom and Express connected accounts) | Only applies to non-US resident Owners | > If we can’t programmatically obtain the full nine digit SSN for an individual associated with your account using information already provided, you must provide the full nine digits. ### New verification error codes When we’re unable to verify information provided by your connected accounts, we’ll surface detailed verification responses as new error codes in the [requirements.errors](https://docs.stripe.com/api/accounts/object.md#account_object-requirements-errors) array. [View docs](https://docs.stripe.com/connect/handling-api-verification.md#validation-and-verification-errors). #### Synchronous errors | Field | New error code | Error message | | --- | --- | --- | | Product Description | `invalid_product_description_length` | Your product description must be at least 10 characters. | | Product Description | `invalid_product_description_url_match` | Your product description must be different from your URL. | | (Full) Statement Descriptor | `invalid_statement_descriptor_length` | Your statement descriptor must be between 5 and 22 characters. | | (Full) Statement Descriptor | `invalid_statement_descriptor_business_mismatch` | Your statement descriptor must be similar to your business name, legal entity name, or URL. | | (Full) Statement Descriptor | `invalid_statement_descriptor_denylisted` | Generic or well-known statement descriptors aren’t supported. | | (Short) Statement Descriptor | `invalid_statement_descriptor_prefix_mismatch` | The statement descriptor prefix must be similar to your statement descriptor, business name, legal entity name, or URL. | | (Short) Statement Descriptor | `invalid_statement_descriptor_prefix_denylisted` | Generic or well-known statement descriptor prefixes aren’t supported. | | LE Business Name | `invalid_company_name_denylisted` | Generic or well-known business names aren’t supported. | | Business Profile Name (DBA) | `invalid_business_profile_name_denylisted` | Generic or well-known business names aren’t supported. | | Business Profile Name (DBA) | `invalid_business_profile_name` | Business profile names must consist of recognizable words. | | Persons DOB | `invalid_dob_age_under_minimum` | Person must be at least 13 years old. | | Persons DOB | `invalid_dob_age_over_maximum` | Date of birth must be within in the last 120 years. | | Persons phone | `invalid_phone_number` | The phone number doesn’t seem to be valid. Make sure it’s formatted correctly. | | LE Business Phone | `invalid_phone_number` | The phone number doesn’t seem to be valid. Make sure it’s formatted correctly. | | Company TaxID | `invalid_tax_id_format` | Tax IDs must be a unique set of 9 numbers without dashes or other special characters. | | URL | `invalid_url_format` | Format as https://example.com | | URL | `invalid_url_denylisted` | Generic business URLs aren’t supported. | #### Asynchronous errors | Field | New error code | Error message | | --- | --- | --- | | URL | `invalid_url_website_inaccessible` | This URL couldn’t be reached. Make sure it’s available and entered correctly or provide another. | | URL | `invalid_url_website_business_information_mismatch` | The business information on your website must match the details you provided to Stripe. | | URL | `invalid_url_website_incomplete` | Your website seems to be missing some required information. Learn about website requirements | | URL | `invalid_url_website_other` | We weren’t able to verify your business using the URL you provided. Make sure it’s entered correctly or provide another URL. | | URL | `invalid_url_web_presence_detected` | Because you use a website, app, social media page, or online profile to sell products or services, you must provide a URL for your business. | ### Update to the threshold at which we verify tax identification numbers (TINs) To align with the IRS reporting thresholds for Forms 1099-K, 1099-NEC, and 1099-MISC, we’re updating the threshold at which we verify the TIN to when your payments volume reaches 600 USD or within 30 days of first charge, whichever comes first. ### How we prefill statement descriptors and statement descriptor prefixes If not provided, the statement descriptor is prefilled using the following supplied fields (in this order): [business_profile.name](https://docs.stripe.com/api/accounts/object.md#account_object-business_profile-name) (“doing business as”), [business_profile.url](https://docs.stripe.com/api/accounts/object.md#account_object-business_profile-url), the legal entity name (either [individual.first_name](https://docs.stripe.com/api/accounts/object.md#account_object-individual-first_name) + [individual.last_name](https://docs.stripe.com/api/accounts/object.md#account_object-individual-last_name) or [company.name](https://docs.stripe.com/api/accounts/object.md#account_object-company-name))`. In addition, if the statement descriptor prefix isn’t provided, it’s prefilled from the first 10 characters of the statement descriptor. ## See also - [Connect onboarding for Custom accounts](https://docs.stripe.com/connect/custom/hosted-onboarding.md) - [Onboarding solutions for Custom accounts](https://docs.stripe.com/connect/custom/onboarding.md) - [Updating accounts](https://docs.stripe.com/connect/updating-service-agreements.md) - [Handling identity verification with the API](https://docs.stripe.com/connect/handling-api-verification.md) - [Testing Custom account identity verification](https://docs.stripe.com/connect/testing-verification.md)