# Verify your users’ identity documents

Create sessions and collect identity documents.

This guide explains how to use Stripe Identity to securely collect and verify identity documents.

Send your users to Stripe to upload their identity documents. Here’s what you’ll do:

1. Add a verification button to your webpage that redirects to Stripe Identity.
2. Display a confirmation page on identity document submission.
3. Handle verification results.

## Before you begin

1. [Set up your Stripe account and verify your business](https://dashboard.stripe.com/account/onboarding).
2. Fill out your [Stripe Identity application](https://dashboard.stripe.com/identity/application).
3. (Optional) Customize your brand settings on the [branding settings page](https://dashboard.stripe.com/settings/branding?tab=identity).

You can also start by cloning a [sample integration](https://github.com/stripe-samples/identity) from GitHub.

## Set up Stripe [Server-side]

First, [register](https://dashboard.stripe.com/register) for a Stripe account.

Then install the libraries for access to the Stripe API from your application:

#### Ruby

```bash
# Available as a gem
sudo gem install stripe
```

```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```

## Add a button to your website [Client-side]

Create a button on your website for starting the verification.

#### HTML + JS

### Add a button

Start by adding a verify button to your page:

```html
<html>
  <head>
    <title>Verify your identity</title>
  </head>
  <body>
    <button id="verify-button">Verify</button>
  </body>
</html>
```

#### React

### Add a button

Start by adding a verify button to your page:

```jsx
import React from 'react';

class VerifyButton extends React.Component {
  render() {
    return (
      <button role="link">
        Verify
      </button>
    );
  }
}

const App = () => {
  return (
    <VerifyButton/>
  );
};

export default App;
```

## Redirect to Stripe Identity [Client-side] [Server-side]

Set up the button to redirect to Stripe Identity. After clicking the button, your frontend redirects to a Stripe-hosted page where they can capture and upload a picture of their passport, driver’s license, or national ID.

The redirect to Stripe Identity cuts down on development time and maintenance and gives you added security. It also decreases the amount of private information you handle on your site, allows you to support users in a variety of platforms and languages, and allows you to customize the style to match your branding.

### Create a VerificationSession

A [VerificationSession](https://docs.stripe.com/api/identity/verification_sessions.md) is the programmatic representation of the verification. It contains details about the type of verification, such as what [check](https://docs.stripe.com/identity/verification-checks.md) to perform. You can [expand](https://docs.stripe.com/api/expanding_objects.md) the [verified outputs](https://docs.stripe.com/api/identity/verification_sessions/object.md#identity_verification_session_object-verified_outputs) field to see details of the data that was verified.

After successfully creating a `VerificationSession`, send the [session URL](https://docs.stripe.com/api/identity/verification_sessions/object.md#identity_verification_session_object-url) to the frontend to redirect to Stripe Identity.
![](https://b.stripecdn.com/docs-statics-srv/assets/modal_integration_diagram.4c9ef035ee7fcb8b8f58a99fcad27202.svg)

You can use verification flows for re-usable configuration, which is passed to the [verification_flow](https://docs.stripe.com/api/identity/verification_sessions/create.md#create_identity_verification_session-verification_flow) parameter. Read more in the [Verification flows guide](https://docs.stripe.com/identity/verification-flows.md).

You need a server-side endpoint to [create the VerificationSession](https://docs.stripe.com/api/identity/verification_sessions/create.md). Creating the `VerificationSession` server-side prevents malicious users from overriding verification options and incurring processing charges on your account. Add authentication to this endpoint by including a user reference in the session metadata or storing the session ID in your database.

#### Node.js

```javascript

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');

// In the route handler for /create-verification-session:
// Authenticate your user.

// Create the session.
const verificationSession = await stripe.identity.verificationSessions.create({
  type: 'document',
  provided_details: {
    email: 'user@example.com',
  },
  metadata: {
    user_id: '{{USER_ID}}',
  },
});

// Return only the session URL to the frontend.
const url = verificationSession.url;
```

> The session URL is single-use and expires after 48 hours. Don’t store it, log it, embed it in a URL, or expose it to anyone other than the user. Send only the session URL to your frontend to avoid exposing verification configuration or results.

Test your endpoint by starting your web server (for example, `localhost:4242`) and sending a POST request with curl to create a VerificationSession:

```bash
curl -X POST -is "http://localhost:4242/create-verification-session" -d ""
```

The response in your terminal looks like this:

```bash
HTTP/1.1 200 OK
Content-Type: application/json

{ id: "vs_QdfQQ6xfGNJR7ogV6", url: "https://verify.stripe.com/start/QdfQQ6xfxNJR7ogV6Z6Wp..." }
```

### Add an event handler to the verify button

Now that you have a button and an endpoint to create a VerificationSession, modify the button to redirect to the session URL when clicked:

#### HTML + JS

```html
<html>
  <head>
    <title>Verify your identity</title>
    <script src="https://js.stripe.com/dahlia/stripe.js"></script>
  </head>
  <body>
    <button id="verify-button">Verify</button>

    <script type="text/javascript">
      var verifyButton = document.getElementById('verify-button');

      verifyButton.addEventListener('click', function() {
        // Get the VerificationSession client secret using the server-side
        // endpoint you created in step 3.
        fetch('/create-verification-session', {
          method: 'POST',
        })
        .then(function(response) {
          return response.json();
        })
        .then(function(session) {
          // When the user clicks on the button, redirect to the session URL.
          window.location.href = session.url;
        })
        .catch(function(error) {
          console.error('Error:', error);
        });
      });
    </script>
  </body>
</html>
```

#### React

```jsx
import React from 'react';
import {loadStripe} from '@stripe/stripe-js';

class VerifyButton extends React.Component {
  async handleClick(event) {
    // Block native event handling.
    event.preventDefault();

    // Call your backend to create the VerificationSession.
    const response = await fetch('/create-verification-session', { method: 'POST' });
    const session = await response.json();

    // When the user clicks on the button, redirect to the session URL.
    window.location.href = session.url;
  }

  render() {
    return (
      <button role="link" onClick={this.handleClick}>
        Verify
      </button>
    );
  }
}

// Make sure to call `loadStripe` outside of a component's render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('<<YOUR_PUBLISHABLE_KEY>>');

const App = () => {
  return (
    <VerifyButton stripePromise={stripePromise}/>
  );
};

export default App;
```

### Test the redirect

Test that the verify button redirects to Stripe Identity:

- Click the verify button.
- Ensure your browser redirects to Stripe Identity.

If your integration isn’t working:

1. Open the Network tab in your browser’s developer tools.
2. Click the verify button to see if it makes an XHR request to your server-side endpoint (`POST /create-verification-session`).
3. Verify that the request returns a 200 status.
4. Use `console.log(session)` inside your button click listener to confirm that it returns the correct data.

## Handle verification events

[Document checks](https://docs.stripe.com/identity/verification-checks.md#document-availability) are typically completed as soon as the user redirects back to your site and you can retrieve the result from the API immediately. In some rare cases, the document verification isn’t ready yet and must continue asynchronously. In these cases, you’re notified through webhooks when the verification result is ready. After the processing completes, the VerificationSession status changes from `processing` to `verified`.

Stripe sends the following events when the session status changes:

| Event name | Description | Next steps |
| --- | --- | --- |
| [identity.verification_session.verified](https://docs.stripe.com/api/events/types.md#event_types-identity.verification_session.verified) | Processing of all the [verification checks](https://docs.stripe.com/identity/verification-checks.md) have completed, and they’re all successfully verified. | Trigger relevant actions in your application. |
| [identity.verification_session.requires_input](https://docs.stripe.com/api/events/types.md#event_types-identity.verification_session.requires_input) | Processing of all the [verification checks](https://docs.stripe.com/identity/verification-checks.md) have completed, and at least one of the checks failed. | Trigger relevant actions in your application and potentially allow your user to retry the verification. |

Use a [webhook handler](https://docs.stripe.com/identity/handle-verification-outcomes.md) to receive these events and automate actions like sending a confirmation email, updating the verification results in your database, or completing an onboarding step. You can also view [verification events in the Dashboard](https://dashboard.stripe.com/events?type=identity.%2A).

## Receive events and run business actions

### With code

Build a webhook handler to listen for events and build custom asynchronous verification flows. Test and debug your webhook integration locally with the Stripe CLI.

[Build a custom webhook](https://docs.stripe.com/identity/handle-verification-outcomes.md)

### Without code

Use the Dashboard to view all your verifications, inspect collected data, and understand verification failures.

[View your test verifications in the Dashboard](https://dashboard.stripe.com/test/identity/verification-sessions)

## Optional: Show a confirmation page [Client-side]

To provide a user-friendly experience, Identity can redirect to a page on your website after users successfully submit their identity document.

Create a minimal confirmation page:

```html

<html>
  <head><title>Your document was submitted</title></head>
  <body>
    <h1>Thanks for submitting your identity document.</h1>
    <p>
      We are processing your verification.
    </p>
  </body>
</html>
```

Next, update the VerificationSession creation call with a URL for this page in the `return_url` parameter:

#### Node.js

```javascript
const verificationSession = await stripe.identity.verificationSessions.create({
  type: 'document',
  return_url: 'https://{{ YOUR_DOMAIN }}/submitted.html',
  metadata: { user_id: '{{USER_ID}}' },
});
```

### Test the confirmation page

Test that your confirmation page works:

- Click your verify button.
- Submit the session by selecting a predefined test case.
- Confirm that the new confirmation page is shown.
- Test the entire flow for failure cases (such as declining consent or refusing camera permissions) and ensure your app handles them without any issues.

Next, find the verification in the Stripe Dashboard. Verification sessions appear in the Dashboard’s [list of VerificationSessions](https://dashboard.stripe.com/identity). Click a session to go to the Session details page. The summary section contains verification results, which you can use in your app.

## See also

- [Handle verification outcomes](https://docs.stripe.com/identity/handle-verification-outcomes.md)
- [Learn about VerificationSessions](https://docs.stripe.com/identity/verification-sessions.md)
- [Learn about Stripe.js](https://docs.stripe.com/payments/elements.md)
