Verify documents with hosted experience

You can use identity verification to securely verify the identity of your customers using documents like their driver’s license or passport—such as before allowing them to open a new bank account online or pick up a rental car. This describes how to quickly integrate identity verification into your website using Transmit Security's hosted identity experience.

Check out our sample app

How it works

Here's an example of a basic integration flow. Transmit APIs are shown in pink along with the relevant integration step.

When the user performs an action requiring identity verification, a session is created from the backend to establish a secure context for the flow (Step 3). Your app redirects the user to the Transmit identity verification experience (Step 4). Once the user completes the verification process, the browser is redirected back to your app to indicate the process completed. You can now get the verification result (Step 5), and then proceed accordingly.

Step 1: Create your app

To integrate with Transmit, you'll need to create an application in the Admin Portal (if you don’t have one yet).

  1. From Applications , click Add application .
  2. Add the friendly application name to display in the Admin Portal.
  3. Add a client display name, and your website URL as a redirect URI (e.g., https://your-domain.com ).
    Note

    These fields are required for Transmit apps, but won’t be used for the identity verification flow.

  4. Click Add to create your application. This will automatically generate your client credentials.

Step 2: Get access token

You’ll need an OAuth2 bearer access token to authorize the backend API requests. Using the client ID and client secret of your Transmit application, send this request from your backend to generate an access token:

Copy
Copied
curl -i -X POST \
  https://api.transmitsecurity.io/oidc/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_secret=[CLIENT_SECRET]' \
  -d grant_type=client_credentials \
  -d resource=https://verify.identity.security \
  -d 'client_id=[CLIENT_ID]'
Note

The token must be requested for the https://verify.identity.security resource, which will appear in the audience claim of the generated token (in the future we’ll block access to tokens without this audience). The token must remain secure on your server, and must only be used for backend requests.

Step 3: Create session

A session is required to provide a secure context for the identity verification flow. Using the access token generated in Step 2, create a session by sending a backend request like this (see the API reference for details):

Copy
Copied
 curl --location --request POST 'https://api.transmitsecurity.io/verify/api/v1/verification
' \
 --header 'Content-Type: application/json' \
 --header 'Authorization: Bearer [ACCESS_TOKEN]' \
 --data-raw '{
     "state": "12345",
     "callback_url": "https://[YOUR_DOMAIN]/[YOUR_CALLBACK_URL]"
 }'
  • callback_url is the page the user will be redirected to when the verification process is completed.
  • state should be replaced with a unique token per request. It will be returned in the redirect URL so you can use it to match the verification result with this request.

The response contains a start token, a session ID, an expiration time, and the images you need to capture. For example:

Copy
Copied
{
  // Use the start token to start the verification on the client side
  "start_token": "abcd6ed78c8c0b7824dfea356ed30b72",
  "session_id": "EXAMPLEskjzsdhskj4",
  "expiration": "2023-12-27T11:59:07.420Z",
  // Array of images to capture
  "missing_images": [
      "document_front",
      "document_back",
      "selfie"
  ]
}

Step 4: Initiate ID verification

After creating the session and obtaining a start token, initiate the verification process by redirecting the user to the following page, which will guide them through the entire identity verification flow:

Copy
Copied
 https://api.transmitsecurity.io/verify/app/[START_TOKEN]

For desktop devices:

In this phase, the identity verification UI is optimized for mobile. It still works on desktop, but the experience is sub-optimal. If the user is on a desktop, redirect them to a mobile device to perform the verification process. We suggest displaying a QR code (encoding the URL above) that the user will scan to initiate the process on mobile. In an upcoming phase, the desktop-to-mobile UI will be provided by Transmit as well.

Step 5: Get verification result

Once the verification is completed, the user is redirected back to your website to the callback URL specified in the verification start request. The URL will include the state from your request, and the session ID. For example:

Copy
Copied
 https://[YOUR_DOMAIN]/[YOUR_CALLBACK_URL]?state=12345&sessionId=ca766ed78c8c0b7824dfea356ed30b72

Using the access token from Step 2 and the session ID, get the verification result by sending this backend request (see API reference):

Copy
Copied
 curl --location --request GET 'https://api.transmitsecurity.io/verify/api/v1/verification/{SESSION_ID}/result' \
 --header 'Content-Type: application/json' \
 --header 'Authorization: Bearer [ACCESS_TOKEN]'

For desktop devices:

After displaying the QR code on the desktop device, you can start polling for the verification status by sending a request like the one above. For example, you can use this to update the desktop experience once the user completes the verification process on their mobile device.

Step 6: Handle verification result

Your service should define the user experience based on the verification result, indicated by the recommendation field:

  • If ALLOW : the identity verification process was completed successfully. The response includes user details collected from the document (like their name and birthday), which can be used to enrich the user's profile, and details about the document used to prove their identity.
  • If CHALLENGE : the identity verification process didn’t succeed, since at least one verification check didn’t pass. The response includes extracted (yet unverified) info and indicates which checks didn't pass and why. This info can be used to review unsuccessful sessions or analyze failed verification attempts. You should proceed as suitable for your use case, typically by initiating a manual review process.
  • If DENY : the identity verification indicates a high likelihood of attempted fraud. The response includes the extracted (yet unverified) info and indicates which checks didn't pass and why. You should block the user or initiate an in-depth manual review to avoid onboarding a fraudulent user.

Collected information is arranged inside nested objects: person, document, and additional_info.

Besides the composite verification result, the response provides information about individual checks inside the nested checks object.

Here's a response example for successful ID verification:

Copy
Copied
{
  "session_id": "H1I12oskjzsdhskj4",
  "status": "complete",
  "recommendation": "ALLOW",
  "person": {
    "full_name": "Marie Salomea Skłodowska-Curies",
    "given_name": "Marie",
    "surname": "Curies",
    "national_id": "123ABC",
    "date_of_birth": "1867-11-07T00:00:00.000Z"
  },
  "document": {
    "country": "US",
    "region": "NY",
    "type": "national_id",
    "number": "1234567",
    "serial_number": "1234567",
    "issue_date": "1867-11-07T00:00:00.000Z",
    "expiration_date": "1867-11-07T00:00:00.000Z"
  },
  "additional_info": {
    "address": {
      "country": "USA",
      "region": "Indiana",
      "city": "Indianapolis",
      "street": "Snowy Ridge Road",
      "house_number": "1234",
      "apartment_number": "12",
      "postcode": "56789",
      "full_address": "1234 Snowy Ridge Road Indianapolis, IN 56789"
    },
    "national_status": {
      "citizen": true,
      "resident": true
    },
    "employment": {
      "profession": ""
    }
  },
  "checks": {
    "document_validation": {
      "recommendation": "ALLOW"
    },
    "document_authentication": {
      "recommendation": "ALLOW"
    },
    "document_liveness": {
      "recommendation": "ALLOW"
    },
    "biometric_matching": {
      "recommendation": "ALLOW"
    },
    "biometric_liveness": {
      "recommendation": "ALLOW"
    },
    "flagged_identity": {
      "recommendation": "ALLOW"
    },
    "risk_recommendation": {
      "recommendation": "ALLOW"
    }
  }
}

The response indicates when checks fail and why:

Copy
Copied
{
  "session_id": "string",
  "status": "complete",
  "recommendation": "DENY",
  // EXTRACTED DATA...
  "checks": {
    "document_validation": {
      "recommendation": "ALLOW"
    },
    "document_authentication": {
      "recommendation": "ALLOW"
    },
    "document_liveness": {
      "recommendation": "DENY",
      "reasons": [ "presentation_attack" ]
    },
    "biometric_matching": {
      "recommendation": "CHALLENGE",
      "reasons": [ "biometric_mismatch" ]
    },
    "biometric_liveness": {
      "recommendation": "DENY", 
      "reasons": [ "mask detected" ]
    },
    "flagged_identity": {
      "recommendation": "DENY",
      "reasons": [ "multiple_same_identity_attempts" ]
    },
    "risk_recommendation": {
      "recommendation": "DENY",
      "reasons": [ "action_is_suspected_fraud" ]
    }
  }
}