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.
This document assumes you’re familiar with API onboarding, how to update accounts, and identity verification.
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, 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 before it can receive payouts. For this example, the identity. is set to company and the external_ uses a tokenized Stripe test account as a reminder to avoid exposing sensitive information in API calls.
Nota
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. and request the card_ and stripe_ capabilities. The examples below show a platform-controlled account with the merchant and recipient configurations.
At this point, the account is created but charges and payouts aren’t enabled until you fulfill verification requirements and attach a payout method. Check the requirements. array to determine the information you need to collect. Currently required entries have a minimum_ of currently_.
{ "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.
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 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.
Nota
For accounts with business_type set to individual, provide at least one individual property (for example, individual.) and a Person object is created automatically. If you don’t, or for accounts with the business_ set to company, you need to create each Person for the account.
When you create a Person, the response includes a requirements. hash listing the required verification information for that person.
{ "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. includes descriptions that reference the Person ID.
Update the Person to provide the requested verification information for Jenny Rosen:
Setting relationship. to true confirms to Stripe that the representative has significant control over the organization. US required verification information 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.
You must add all owners that have at least 25% ownership of the company, then set identity. to 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.webhook event from Stripe.core. account. updated
Testing thresholds
Whether you use up-front onboarding or incremental onboarding, 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. array for requirements with a minimum_ of eventually_.
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 token (tok_) 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 webhook event, you can check:
requirements.for entries whereentries minimum_isdeadline. status currently_due requirements.to find out the earliest deadline that applies to those entriessummary. minimum_ deadline. time
To test scenarios where required information isn’t provided by the deadline, see the blocking charges and payouts sections below.
You can also trigger more specific verification triggers, like an identity mismatch or an OFAC threshold. 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 token (tok_). After doing so, you receive a v2.core.account[requirements].updated webhook event that shows:
- The relevant capability status for card payments isn’t
active(for example,configuration.isn’tmerchant. capabilities. card_ payments. status active) - The required information in the
requirements.array (withentries minimum_anddeadline. status currently_)due - Any entries that aren’t required yet appear with
minimum_anddeadline. status eventually_due
You can then update the account 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 token (tok_). After doing this, you should receive a v2. webhook event that shows:
capabilities.in thestripe_ balance. payouts. status merchantorrecipientconfiguration isn’tactive- Currently required information in the
requirements.array with aentries minimum_ofdeadline. status currently_due - Eventually required information in the
requirements.array with aentries minimum_ofdeadline. status eventually_due
You can then update the account with the new information. That triggers another webhook event, which indicates that payouts are enabled and that the requirements. and requirements. arrays are both empty.