Handling verification with the API
Learn how Connect platforms with Custom accounts can use webhooks and the API to handle identity and business verification.
Platforms with Custom accounts are required to provide Stripe with necessary information about their users for Know Your Customer (KYC) purposes. As a Connect platform with Custom accounts, it’s your responsibility to collect the required information from your users and provide it to Stripe. We’ll then perform verification, asking for more information when needed.
The rest of this page goes through how platforms:
- Know when identity or business verification is needed
- Provide the necessary information to Stripe
You should also read the Identity Verification for Custom Accounts guide to learn about the verification flow options, how the API fields translate to both companies and individuals, and how to localize information requests.
Verification process
Before charges and payouts can be enabled for a connected account, Stripe needs a certain set of information. The specific needs vary depending on the:
- The country the connected account is in.
- The capabilities the connected account needs.
- Whether the business entity is a company or an individual.
Platforms need to choose the proper onboarding flow for their business and users to meet the KYC requirements. Broadly speaking, this means providing all the requisite information upfront or incrementally. Either way, you’ll need to be set up to watch for and respond to requests from Stripe.
- Establish a platform webhook URL in your webhook settings to watch for activity, especially events of the
account.updated
type. When using the Persons API, you should also watch forperson.updated
events. - Immediately after creating an account, check the
Account
object’srequirements[currently_due]
attribute for any additional requirements. If additional information is required, obtain it from the user and update the connected account. - Continue watching for
account.updated
event notifications to see if therequirements
hash changes, and reaching out to your user for additional information as needed.
Note that when you provide additional information, you do not need to resubmit any previously verified details (e.g., if the dob
has already been verified, it does not need to be provided again in subsequent updates).
Once an individual is verified, you cannot change that individual’s information. For verified companies, you’ll need to contact support to make changes (e.g., the name or EIN on file).
Determining if identity or business verification is needed
When you receive an account.updated
webhook notification or fetch an account via the API, you receive an Account object. The Account
object’s charges_enabled
and payouts_enabled
indicate whether the account can create charges and accept payouts.
The Account
object has a requirements
hash, representing the requirements needed to verify the account. The requirements
hash has three arrays:
eventually_due
: Information in this array isn’t needed immediately, but it will be when certain thresholds are hit. All required information starts in this array.currently_due
: Information in this array needs to be collected by thecurrent_deadline
and is a subset ofeventually_due
.past_due
: Information in this array means the account is disabled because the required information wasn’t collected.past_due
is a subset ofcurrently_due
.
The example below shows what the requirements
hash might look like for an account that has some information that’s currently_due
, and some information that’s eventually_due
.
{ "requirements": { "disabled_reason": null, "current_deadline": 1529085600, "past_due": [], "currently_due": [ "external_account", "individual.dob.day", "individual.dob.month", "individual.dob.year", "individual.first_name", "individual.last_name", "tos_acceptance.date", "tos_acceptance.ip" ], "eventually_due": [ "external_account", "individual.address.city", "individual.address.line1", "individual.address.postal_code", "individual.address.state", "individual.dob.day", "individual.dob.month", "individual.dob.year", "individual.first_name", "individual.last_name", "individual.ssn_last_4", "tos_acceptance.date", "tos_acceptance.ip" ], }, ... }
If requirements[currently_due]
is not an empty array, requirements[current_deadline]
might be set. This is a Unix timestamp identifying when the information is needed. Usually, if Stripe does not receive the information by the current_deadline
, payouts on the account are disabled. However, there can be other consequences for rarer situations. For example, if payouts are already disabled and our inquiries are not being responded to within a reasonable period of time, Stripe might also disable the ability to process charges.
Separately, the requirements[disabled_reason]
property might also be set. This is a string describing the reason why this account is unable to make payouts or charges. The reason can fall into several categories.
Reason | Meaning |
---|---|
fields_needed |
Additional verification information is required to enable payout or charge capabilities on this account |
listed |
Account might be on a prohibited persons or companies list (Stripe will investigate and either reject or reinstate the account appropriately) |
rejected.fraud |
Account is rejected due to suspected fraud or illegal activity |
rejected.listed |
Account is rejected because it is on a third-party prohibited persons or companies list (such as financial services provider or government) |
rejected.terms_of_service |
Account is rejected due to suspected terms of service violations |
rejected.other |
Account is rejected for another reason |
under_review |
Account is under review by Stripe |
other |
Account is not rejected but is disabled for another reason while being reviewed |
Person information
During the verification process, information about the persons associated with an account needs to be collected. If you onboard:
- Only companies, use the Persons API to collect this information.
- Only individuals, you can use the Persons API or the individual hash on the Account object.
- A combination of individuals and companies, use the Persons API to collect this information. This way you collect information in the same manner regardless of business type.
You can use a verification
subhash to help manage identity verification on both the Person object and the individual
hash (you should also watch for person.updated events so you know when there are changes).
{ "verification": { "details": null, "details_code": null, "document": null, "additional_document": null, "status": "unverified" }, ... }
The Account object has a verification
subhash as well:
{ "verification": { "document": null } }
You can look up the definition for each verification attribute on the Person object or the Account object, but there are two attributes worth noting now: status
and details
.
status
indicates the current verification state for the person and has three possible values.
pending
: Stripe is currently trying to verify this entity.unverified
: Stripe is not able to verify this entity right now, either because verification has failed or because we don’t have enough information to attempt verification.verified
: Stripe has successfully verified this entity.
Note that an unverified
status is not necessarily an urgent issue, but it does mean that Stripe might request more information soon.
The details
attribute provides an explanation for the current status
. This explanation can be shared with the user so they can understand why their account is in the current state.
Acceptable ID types by country
Below is a listing of documents that Stripe can accept as proof of identity for each country where Stripe supports the creation of Connect accounts.
Acceptable ID documents vary by country, however, a passport scan is always acceptable and is preferred. There are some forms of identification that require scans of both the front and back of the ID. For these, use the document_back
parameter to provide the back of the document. Unless explicitly noted, only a scan of the front of the ID is required.
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- Photo card (New South Wales)
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- National ID
- Resident permit ID
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID
- Consular ID
- Resident permit ID
- eCard — scans of front and back are required
- fCard — scans of front and back are required
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- National ID
- Resident permit ID
- Marina ID
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- Identification card — scans of front and back are required
- Alberta
- Nova Scotia
- Saskatchewan
- Nunavut
- Identity card — scans of front and back are required
- British Columbia
- Carte d'identité — scans of front and back are required
- Manitoba
- New Brunswick
- Nova Scotia
- Northwest territories
- Carte d'identification — scans of front and back are required
- New Brunswick
- Newfoundland and Labrador
- Prince Edward Island
- Carte-photo — scans of front and back are required
- Ontario
- Carte d'identité générale — scans of front and back are required
- Yukon
- National ID (photo card)
- Resident permit ID (carte de résident)
- Certificat de citoyenneté canadienne
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- Resident permit ID
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID (henkilökortin)
- Resident permit ID
- Minor's ID (alaikäisen henkilökortin)
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- National ID (carte nationale d'identité)
- Resident permit ID (titre de séjour)
- French VTC card
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID
- Resident permit ID
Acceptable forms of identification are:
- Passport
- ID card
- National ID/Hong Kong permanent identity card/New Hong Kong ID card
- Resident permit ID/Hong Kong identity card
- Mainland Travel Permit for Hong Kong
Acceptable forms of identification are:
- Passport/Irish Passport Card
- Driver license
- ID card — scans of front and back are required
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- National ID (carta di identità)
- Resident permit ID (permesso di soggiorno)
- Military card
- Public safety card
- Personal ID card
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card
- Resident permit ID/Japan resident card/Special Permanent Resident Certificate
- Individual Number Card
- Alien Registration Card
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID
- Resident permit ID
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- Consular ID/Matricular Consular ID Card
- Instituto Federal Electoral Registro (voter ID card)
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- National ID
- Resident permit ID (verblijfstitel)
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
Acceptable forms of identification are:
- Passport
- Driver license
- ID card
- Resident permit ID
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID
- Resident permit ID
Acceptable forms of identification are:
- Passport
- Driver license — scans of front and back are required
- ID card — scans of front and back are required
- National ID/National Registration Identity Cards for citizens/National Registration Identity Card for permanent residents
- Singapore Employment Pass/S Pass/Entree Pass/Personalized Employment Pass/Training Employment Pass/Work Holiday Pass/Work Permit Pass/Visit Pass/Dependent’s Pass/Long Term Visit Pass/Long Term Visit Pass +/Student Pass
- Singapore Armed Forces
- Singapore National Service Identity Card
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID/Documento nacional de identidad (DNI)
- Resident permit ID/Tarjeta de Identidad de Extranjero Card
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID
- Swedish Standards Institute (SIS) approved ID cards as national ID:
- Sparbanken
- Handelsbanken
- Skåne
- Danske Bank
- Nordea
- Swedbank
- SEB bank
- Tranås Kommun
- Stockholms läns landsting
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- National ID
- Resident permit ID/National ID Card for foreigners
Acceptable forms of identification are:
- Passport
- Driver license
- ID card — scans of front and back are required
- Resident permit ID/IND application registration card (ARC)/UK permanent residence document
- Citizen Card
- Electoral ID
- Validate UK (proof of age card)
Acceptable forms of identification are:
- Passport/Passport Card
- Driver license — scans of front and back are required
- ID card (by U.S. state) — scans of front and back are required
- Resident permit ID/U.S. Green Card/North Carolina Resident ID
- Border Crossing Card
- Child ID card
- NYC Card
- U.S. visa card
Handling document verification problems
Many complications with the verification process involve the uploaded document itself. To help you recognize and handle the most common problems, the table below lists the details_codes
(on the verification
subhash) and the likely resolutions for each error.
Error | Resolution |
---|---|
document_corrupt |
The upload failed due to a problem with the file itself. Ask your user to provide a new file that meets these requirements: a color image (smaller than 8,000px by 8,000px), in JPG or PNG format, and less than 10 MB in size. |
document_country_not_supported |
The provided file is not an acceptable form of ID from a supported country. Ask your user to provide a new file that meets that requirement. For a listing, see Acceptable ID types by country. |
failed_keyed_identity |
The name on the account could not be verified. Ask your users to verify they provided their full legal name and provide a photo ID matching that name. |
failed_other |
Your team may contact Stripe to learn more about why identity verification failed. |
document_name_mismatch |
The information on the ID document doesn't match the information provided by the user. Ask your user to verify and correct the provided information on the account. |
document_expired |
The document is expired. If it’s an identity document, its expiration date must be before the date the document was submitted. If it’s an address document the issue date must be within the last six months. |
Handling identity verification
There are two ways to respond to an identity verification change. The first is to perform an update account call, correcting or adding information.
Secondarily, we might ask you to upload a document. Depending on how much of the user’s information Stripe has been able to verify, we might require three different types of document uploads. You can determine what documents to upload based on the fields listed in requirements[currently_due]
:
person.verification.document
: Requires a color scan or photo of an acceptable form of ID.person.verification.additional_document
: Requires a color scan or photo of a document verifying the user’s address, such as a utility bill.company.verification.document
: Requires a proof of entity document establishing the business’ entity ID number, such as the company’s articles of incorporation.
Uploading a document is a two-step process:
- Upload the file to Stripe
- Attach the file to the account
Uploading a file
To upload a file, POST it as part of a multipart/form-data request to https://files.stripe.com/v1/files
. The uploaded file needs to be a color image (smaller than 8,000px by 8,000px), in JPG or PNG format, and less than 10 MB in size.
Pass the file in the file
parameter and set the purpose
parameter to identity_document
:
curl https://files.stripe.com/v1/files \ -u {PLATFORM_SECRET_KEY}: \ -H "Stripe-Account: {{CONNECTED_STRIPE_ACCOUNT_ID}}" \ -F purpose=identity_document \ -F file="@/path/to/a/file"
Stripe.api_key = PLATFORM_SECRET_KEY Stripe::FileUpload.create( { purpose: 'identity_document', file: File.new('/path/to/a/file.jpg'), }, {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID} )
stripe.api_key = PLATFORM_SECRET_KEY with open("/path/to/a/file.jpg", "rb") as fp: stripe.FileUpload.create( purpose='identity_document', file=fp, stripe_account=CONNECTED_STRIPE_ACCOUNT_ID )
\Stripe\Stripe::setApiKey(PLATFORM_SECRET_KEY); \Stripe\FileUpload::create( [ 'purpose' => 'identity_document', 'file' => fopen('/path/to/a/file.jpg', 'r') ], ['stripe_account' => CONNECTED_STRIPE_ACCOUNT_ID] );
Stripe.apiKey = PLATFORM_SECRET_KEY; RequestOptions requestOptions = RequestOptions.builder().setStripeAccount(CONNECTED_STRIPE_ACCOUNT_ID).build(); Map<String, Object> fileUploadParams = new HashMap<String, Object>(); fileUploadParams.put("purpose", "identity_document"); fileUploadParams.put("file", new File("/path/to/a/file.jpg")); FileUpload.create(fileUploadParams, requestOptions);
var fs = require('fs'); const stripe = require('stripe')(PLATFORM_SECRET_KEY); stripe.fileUploads.create( { purpose: 'identity_document', file: { data: fs.readFileSync('/path/to/a/file.jpg'), name: 'file_name.jpg', type: 'application/octet-stream' } }, {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID} );
fp, err := os.Open("/path/to/a/success.png") params := &stripe.FileUploadParams{ FileReader: fp, Filename: stripe.String("success.png"), Purpose: stripe.String(string(stripe.FileUploadPurposeIdentityDocument)), } params.SetStripeAccount("{{CONNECTED_STRIPE_ACCOUNT_ID}}") file_upload, err := fileupload.New(params)
This request uploads the file and returns a token:
{ "id": "file_5dtoJkOhAxrMWb", "created": 1403047735, "size": 4908 }
You may then use the token’s id
value to attach the file to a connected account for identity verification.
Attaching the file
After the file has been uploaded and a representative token has been returned, provide the file ID using the appropriate field in your update account call.
Below is an example for an ID document:
curl https://api.stripe.com/v1/accounts/{{CONNECTED_STRIPE_ACCOUNT_ID}}/persons/{{PERSON_ID}} \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "verification[document][front]"=file_5dtoJkOhAxrMWb
Below is an example for a company document:
curl https://api.stripe.com/v1/accounts/{{CONNECTED_STRIPE_ACCOUNT_ID}} \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "company[verification][document][front]"=file_5dtoJkOhAxrMWb
This update changes verification[status]
to pending
. If additional persons needs to be verified, use the Persons API to update them.
Confirming ID verification
If the color scan or photo of the ID passes Stripe’s checks, the document requirement is removed from requirements[currently_due]
. If you have satisfied all verification requirements for the person or company, the verification[status]
field is updated to verified
. You also receive an account.updated
webhook notification when the verification process is complete.
Verification can take Stripe from a few minutes, to a couple business days to complete, depending on how readable the provided image is.
If the verification attempt fails, the status is unverified
and the details
field contains a message stating the cause. The message is safe to present to your user, such as “The image supplied was not readable”. In addition, the response contains a details_code
value, such as scan_not_readable
. Upon failure, requirements[currently_due]
indicates that a new ID upload is required. If the deadline for verification is near, requirements[current_deadline]
may also be populated with a date. Again, an account.updated
webhook notification is sent as well.
Further reading
Now that you know how to perform identity verification through the API, you may want to read: