# Testing account verification during API onboarding A walk-through of testing different verification states for connected accounts during API onboarding using your test API key. # Accounts v2 This document assumes you’re familiar with [API onboarding](https://docs.stripe.com/connect/api-onboarding.md), how to [update accounts](https://docs.stripe.com/connect/updating-service-agreements.md), and [identity verification](https://docs.stripe.com/connect/identity-verification.md). Test your verification flows to make sure they can handle changes in account state (for example, when you enable or disable charges). Account states generally change after fulfilling requirements or when reaching processing or time thresholds. The sections below describe these changes and how to test your verification flows. ## Testing initial requirements Start by creating a new connected account in a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes), adding a bank account, and showing that the account holder accepted the Stripe Services Agreement. Stripe requires that the connected account explicitly accept [Stripe’s service agreement](https://docs.stripe.com/connect/updating-service-agreements.md#tos-acceptance) before it can receive payouts. For this example, the `identity.entity_type` is set to `company` and the `external_account` uses a tokenized Stripe test account as a reminder to avoid exposing sensitive information in API calls. > You must provide a test API key from a Stripe account that has begun Connect platform onboarding. The auto-filled Stripe test API key causes these sample requests to fail. When you create the `Account`, you must set `identity.country` and request the `card_payments` and `stripe_balance.stripe_transfers` capabilities. The examples below show a platform-controlled account with the `merchant` and `recipient` configurations. ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-11-17.preview" \ --json '{ "identity": { "country": "US", "entity_type": "company", "attestations": { "terms_of_service": { "account": { "date": "2019-01-19T19:51:13Z", "ip": "172.18.80.19" } } } }, "dashboard": "none", "defaults": { "responsibilities": { "losses_collector": "application", "fees_collector": "stripe" }, "currency": "usd" }, "configuration": { "merchant": { "capabilities": { "card_payments": { "requested": true } } }, "recipient": { "capabilities": { "stripe_balance": { "stripe_transfers": { "requested": true } } } } } }' ``` At this point, the account is created but charges and *payouts* (A payout is the transfer of funds to an external account, usually a bank account, in the form of a deposit) aren’t enabled until you fulfill verification requirements and attach a payout method. Check the `requirements.entries` array to determine the information you need to collect. Currently required entries have a `minimum_deadline.status` of `currently_due`. ```json { "id": "{% identifier type=\"connectedAccount\" quoteType=\"double\" /%}", "object": "account", "identity": { "country": "US", "entity_type": "company" }, "dashboard": "none", "defaults": { "responsibilities": { "losses_collector": "application", "fees_collector": "stripe" }, "currency": "usd" }, "configuration": { "merchant": { "capabilities": { "card_payments": { "status": "restricted", "status_details": [ { "code": "determining_status", "resolution": "provide_info" } ] } } }, "recipient": { "capabilities": { "transfers": { "status": "restricted", "status_details": [ { "code": "determining_status", "resolution": "provide_info" } ] } } } }, "requirements": { "summary": { "minimum_deadline": { "time": 1700000000, "status": "currently_due" } }, "entries": [ { "id": "reqent_1", "description": "configuration.merchant.mcc", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_2", "description": "defaults.profile.business_url", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_3", "description": "identity.business_details.address.city", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_4", "description": "identity.business_details.address.line1", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_5", "description": "identity.business_details.address.postal_code", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_6", "description": "identity.business_details.address.state", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_7", "description": "identity.business_details.registered_name", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_8", "description": "identity.business_details.phone", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_9", "description": "identity.business_details.id_numbers.us_ein", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_10", "description": "relationship.representative", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] }, { "id": "reqent_11", "description": "relationship.owner", "minimum_deadline": { "status": "currently_due" }, "awaiting_action_from": "user", "errors": [] } ] } } ``` Then, collect the required information identified in the response and add it to the Account object. ```curl curl -X POST https://api.stripe.com/v2/core/accounts/{{CONNECTEDACCOUNT_ID}} \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-11-17.preview" \ --json '{ "defaults": { "profile": { "business_url": "https://bestcookieco.com" } }, "identity": { "business_details": { "address": { "city": "Schenectady", "line1": "123 State St", "postal_code": "12345", "state": "NY" }, "id_numbers": [ { "type": [ "us_ein" ], "value": "000000000" } ], "phone": "8888675309", "registered_name": "The Best Cookie Co" } } }' ``` After updating business details, the requirements entries might change. For `Person` requirements, you must create and update `Person` objects under the `Account` object for the people that represent or own the company. Use the [Persons](https://docs.stripe.com/api/v2/core/persons.md?api-version=2025-11-17.preview) API to create a profile for each person with an owner or representative relationship to the account. For this example, we create a profile for Jenny Rosen, and identify her as the `representative` with the `title` of `CEO`. ```curl curl -X POST https://api.stripe.com/v2/core/accounts/{{CONNECTEDACCOUNT_ID}}/persons \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-11-17.preview" \ --json '{ "given_name": "Jenny", "surname": "Rosen", "relationship": { "representative": true, "title": "CEO" } }' ``` > For accounts with [business_type](https://docs.stripe.com/api/accounts/object.md#account_object-business_type) set to `individual`, provide at least one `individual` property (for example, `individual.first_name`) and a [Person](https://docs.stripe.com/api/persons/object.md) object is created automatically. If you don’t, or for accounts with the `business_type` set to `company`, you need to [create each Person](https://docs.stripe.com/api/persons/create.md) for the account. When you create a `Person`, the response includes a `requirements.entries` hash listing the required verification information for that person. ```json { "id": "person_abc", "object": "person", "requirements": { "entries": [ { "id": "p_req_1", "description": "representative.address.city", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_2", "description": "representative.address.line1", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_3", "description": "representative.address.postal_code", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_3", "description": "representative.address.state", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_4", "description": "representative.date_of_birth.day", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_5", "description": "representative.date_of_birth.month", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_6", "description": "representative.date_of_birth.year", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_7", "description": "representative.phone", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_8", "description": "representative.email", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_9", "description": "identity.attestations.persons_provided.owners", "minimum_deadline": { "status": "currently_due" }, "errors": [] }, { "id": "p_req_10", "description": "representative.id_numbers. us_ssn_last_4", "minimum_deadline": { "status": "currently_due" }, "errors": [] } ] } } ``` After you create a `Person` and provide the requested person-level details, the Account’s `requirements.entries` includes descriptions that reference the [Person ID](https://docs.stripe.com/api/v2/core/persons/object.md?api-version=2025-11-17.preview#v2_person_object-id). [Update the Person](https://docs.stripe.com/api/v2/core/persons/update.md?api-version=2025-11-17.preview) to provide the requested verification information for Jenny Rosen: ```curl curl -X POST https://api.stripe.com/v2/core/accounts/{{CONNECTEDACCOUNT_ID}}/persons/{{PERSON_ID}} \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-11-17.preview" \ --json '{ "address": { "city": "Schenectady", "line1": "123 State St", "postal_code": "12345", "state": "NY" }, "date_of_birth": { "day": 10, "month": 11, "year": 1980 }, "id_numbers": [ { "type": [ "us_ssn_last_4" ], "value": "0000" } ], "phone": "8888675309", "email": "jenny@example.com", "relationship": { "executive": true } }' ``` Setting `relationship.executive` to true confirms to Stripe that the representative has significant control over the organization. [US required verification information](https://docs.stripe.com/connect/required-verification-information.md#additional-company-card-representative-us) has more information about company representative verification details for US businesses. To add an owner, create another `Person` and mark them as an `owner` for the account. In this example, Kathleen Banks owns 80% of The Best Cookie Co. ```curl curl -X POST https://api.stripe.com/v2/core/accounts/{{CONNECTEDACCOUNT_ID}}/persons \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-11-17.preview" \ --json '{ "given_name": "Kathleen", "surname": "Banks", "email": "kathleen@example.com", "relationship": { "owner": true, "percent_ownership": "80" } }' ``` You must add all owners that have at least 25% ownership of the company, then set `identity.attestations.persons_provided.owners` to true. ```curl curl -X POST https://api.stripe.com/v2/core/accounts/{{CONNECTEDACCOUNT_ID}} \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-11-17.preview" \ --json '{ "identity": { "attestations": { "persons_provided": { "owners": true } } } }' ``` Successful initial onboarding of your connected account at this stage means: - You’ve completed all required information (`requirements.summary.minimum_deadline=null`). - Charges are enabled for the account (`charges_enabled=true`). - You received a `v2.core.account.updated` *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) event from Stripe. ## Testing thresholds Whether you use *up-front onboarding* (Upfront onboarding is a type of onboarding where you collect all required verification information from your users at sign-up) or *incremental onboarding* (Incremental onboarding is a type of onboarding where you gradually collect required verification information from your users. You collect a minimum amount of information at sign-up, and you collect more information as the connected account earns more revenue), Stripe might request more information about connected accounts as those accounts reach certain thresholds. For example, more information might be required after 1,500 USD in charges or 30 days after an account is created. To find out what information might eventually become required if an account reaches a threshold, check the `requirements.entries` array for requirements with a `minimum_deadline.status` of `eventually_due`. If you don’t provide required information by a certain date, charges and payouts might be disabled. You can trigger these scenarios for testing. ### Triggering thresholds You can create a charge with the [verification](https://docs.stripe.com/connect/testing.md#trigger-cards) token (`tok_visa_triggerVerification`) to trigger a generic verification threshold. This doesn’t block charges or payouts, but it does trigger the request for additional information. If you’re listening to the [v2.core.account[requirements].updated](https://docs.stripe.com/api/v2/core/accounts/event-types.md?api-version=2025-11-17.preview#v2_accounts_event_types-v2.core.account%5Brequirements%5D.updated) webhook event, you can check: - `requirements.entries` for entries where `minimum_deadline.status` is `currently_due` - `requirements.summary.minimum_deadline.time` to find out the earliest deadline that applies to those entries To test scenarios where required information isn’t provided by the deadline, see the blocking [charges](https://docs.stripe.com/connect/testing-verification.md#blocked-charges) and [payouts](https://docs.stripe.com/connect/testing-verification.md#blocked-payouts) sections below. You can also trigger more specific verification triggers, like an [identity mismatch](https://docs.stripe.com/connect/testing.md#test-personal-id-numbers) or an [OFAC threshold](https://docs.stripe.com/connect/testing.md#test-dobs). Testing these scenarios is beneficial because they often happen when verification fails. ### Testing blocked charges You can block charges by creating a test charge with the [charge block](https://docs.stripe.com/connect/testing.md#trigger-cards) token (`tok_visa_triggerChargeBlock`). After doing so, you receive a [v2.core.account[requirements].updated](https://docs.stripe.com/api/v2/core/accounts/event-types.md?api-version=2025-11-17.preview#v2_accounts_event_types-v2.core.account%5Brequirements%5D.updated) webhook event that shows: - The relevant capability status for card payments isn’t `active` (for example, `configuration.merchant.capabilities.card_payments.status` isn’t `active`) - The required information in the `requirements.entries` array (with `minimum_deadline.status` and `currently_due`) - Any entries that aren’t required yet appear with `minimum_deadline.status` and `eventually_due` You can then [update the account](https://docs.stripe.com/api/v2/core/accounts/update.md?api-version=2025-11-17.preview) with the new information. That triggers another webhook event, which indicates that charges are enabled and that there are no currently due or eventually due requirements. ### Testing blocked payouts You can block payouts by creating a test charge with the [block transfer](https://docs.stripe.com/connect/testing.md#trigger-cards) token (`tok_visa_triggerTransferBlock`). After doing this, you should receive a `v2.core.account.updated` webhook event that shows: - `capabilities.stripe_balance.payouts.status` in the `merchant` or `recipient` configuration isn’t `active` - Currently required information in the `requirements.entries` array with a `minimum_deadline.status` of `currently_due` - Eventually required information in the `requirements.entries` array with a `minimum_deadline.status` of `eventually_due` You can then [update the account](https://docs.stripe.com/api/v2/core/accounts/update.md?api-version=2025-11-17.preview) with the new information. That triggers another webhook event, which indicates that payouts are enabled and that the `requirements.summary` and `requirements.summary.minimum_deadline` arrays are both empty.