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 test mode, adding a bank account, and showing that the account holder accepted the Stripe Services Agreement. Stripe requires that the connected account explicitly accepts Stripe’s service agreement before making payouts. For this example, the business_
is set to company
to illustrate a more complex scenario, and the external_
uses a tokenized Stripe test account as a reminder to avoid exposing sensitive information in API calls.
Note
You must provide a test API key from a Stripe account which has begun Connect platform onboarding. The auto-filled Stripe test API key causes these sample requests to fail.
You can create a connected account using either controller properties or by setting the account type. In either case, you must set country and request the card_
and transfers
capabilities.
At this point, the account is created but charges and payouts are still disabled. In the response, check the requirements.
array to determine what information you need to collect:
{ "id":
, "object": "account", "requirements": { "currently_due": [ "business_profile.mcc", "business_profile.url", "company.address.city", "company.address.line1", "company.address.postal_code", "company.address.state", "company.name", "company.phone", "company.tax_id", "relationship.representative", "relationship.owner" ], ... }, ... }"{{CONNECTED_ACCOUNT_ID}}"
Then, use the external account id
returned in the response to update the account with the additional required information about the account:
After successfully updating the company details, checking requirements.
shows the relationship
requirements are still required:
{ "id":
, "object": "account", "requirements": { "currently_due": [ "relationship.representative", "relationship.owner", ], ... }, ... }"{{CONNECTED_ACCOUNT_ID}}"
Use the Persons API to create a profile for the person representing the relationship to the account. For this example, we create a profile for Jenny Rosen, and identify her as the representative
. For this example, we also populate the optional title
attribute.
Note
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":
, "object": "account", "requirements": { "currently_due": [ "address.city", "address.line1", "address.postal_code", "address.state", "dob.day", "dob.month", "dob.year", "phone", "email", "relationship.executive", "ssn_last_4" ], ... }, ... }"{{CONNECTED_ACCOUNT_ID}}"
After you create a Person
for your external account, checking the Account
object shows that the required verification information for the newly created Person
has been added to the requirements.
list:
{ "id":
, "object": "account", "requirements": { "currently_due": [ "person.person_xxx.address.city", "person.person_xxx.address.line1", "person.person_xxx.address.postal_code", "person.person_xxx.address.state", "person.person_xxx.dob.day", "person.person_xxx.dob.month", "person.person_xxx.dob.year", "person.person_xxx.phone", "person.person_xxx.email", "person.person_xxx.relationship.executive", "person.person_xxx.ssn_last_4", "relationship.owner" ], ... }, ... }"{{CONNECTED_ACCOUNT_ID}}"
Use the Update a Person API to provide the requested verification information for Jenny Rosen:
Setting relationship[executive]=true
confirms to Stripe that the representative is someone with significant control in the organization. US required verification information has more information about company representative verification details for US businesses.
After providing the representative
information, we still need to identify the owner
for the account. In this example, Kathleen Banks owns 80% of The Best Cookie Co.
In our example, Kathleen Banks owns less than 100% of The Best Cookie Co. Since you haven’t defined another owner to make the ownership total 100%, Stripe requires you to confirm that you’ve provided information on all required owners.
Successful completion of your connected account at this stage means:
- You’ve completed all required information (
requirements.
).currently_ due=null - Charges are enabled for the account (
charges_
).enabled=true - You received an
account.
webhook from Stripe.updated
Testing thresholds
Whether you use upfront onboarding or incremental onboarding, Stripe might request more information about connected accounts as different thresholds are reached. Sometimes these thresholds are triggered by verification failures or OFAC checks. Other times, they’re triggered by a processing or time component. For example, more information might be required after 1,500 USD in charges or 30 days after an account is created (whichever comes first). To find out what information is required and by when, you can check the requirements.
array and the requirements.
timestamp.
In some cases, if the you don’t collect new information by a certain date, charges and payouts might be disabled until you collect it. You can trigger these scenarios so that you can test these thresholds, and then collect the required information.
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 account.
webhook, you can check:
requirements.
to find out what information is needed.currently_ due requirements.
to find out when the information is needed.current_ deadline
If the information isn’t collected by the current_
, charges and payouts might be disabled. To test scenarios like this, see the blocking charges and payouts sections below.
You can also trigger more specific verification thresholds, like when there’s an identity mismatch or when an OFAC threshold is reached. Testing these thresholds 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 this, you should receive an account.
webhook that shows:
charges_
.enabled=false - The required information in the
requirements.
array.currently_ due - An empty
requirements.
array.eventually_ due
You can then update the account with the new information. That triggers another webhook, which indicates that charges are enabled and that the requirements.
and requirements.
arrays are both empty.
Testing blocked payouts
You can block payouts by creating a test charge with the block transfer token (tok_
). After doing this, you should receive an account.
webhook that shows:
payouts_
.enabled=false - The required information in the
requirements.
array.currently_ due - An empty
requirements.
array.eventually_ due
You can then update the account with the new information. That triggers another webhook, which indicates that payouts are enabled and that the requirements.
and requirements.
arrays are both empty.