Skip to main content

Identity Verification

Perform comprehensive identity verification with document checks and liveness detection. The consumer completes verification tasks via the Thirdfort mobile app.

Overview

Use Case: Full identity verification when the consumer is in the flow and can use the mobile app to capture documents and complete liveness checks.

Key Features:

  • Document capture (passport, driving license, ID card)
  • Liveness detection (selfie video)
  • AML screening (sanctions/PEP checks)
  • Optional address verification
  • Optional CCJ/Insolvency check (UK only)
  • Optional ongoing monitoring
  • Consumer completes tasks via mobile app

Subject Type: Individual

Template ID: checkTemplates/identity-verification-check-v1-0-0


When to Use This Check

Good for:

  • Full identity verification with document checks
  • Onboarding new clients who can use mobile app
  • Regulatory compliance requiring document verification
  • High-assurance identity verification

Not suitable for:

  • Quick screening without consumer interaction (use Client-Only Verification instead)
  • Source of funds verification (use Source of Funds instead)
  • Business verification (use KYB Verification instead)

Consumer Journey

  1. Client creates check via API
  2. Consumer receives notification (email/SMS with magic link)
  3. Consumer opens Thirdfort app via magic link
  4. Consumer captures documents (passport, driving license, or ID card)
  5. Consumer completes liveness check (selfie video)
  6. Consumer provides additional data (address, date of birth if not on document)
  7. Check processes (document verification, liveness, AML screening)
  8. Results available via API

Typical completion time: 5-15 minutes (depends on consumer)


Prerequisites

  • Thirdfort account with API access
  • Client credentials (Client ID and Secret)
  • Consumer contact details: Email or phone number for notification
  • Package support: Ongoing monitoring requires package support (if enabled)

Parameters Reference

Required Parameters

ParameterTypeDescription
displayNamestringHuman-readable name for the check
clientReferencestringYour own reference ID for tracking
templatestringMust be checkTemplates/identity-verification-check-v1-0-0
params.@typestringMust be type.googleapis.com/thirdfort.client.checks.type.v1.IdentityVerificationCheckParams
params.subject.givenNamestringFirst name of the individual
params.subject.familyNamestringLast name of the individual
params.subject.email OR params.subject.phoneNumberstringContact method for consumer notification

Optional Parameters

ParameterTypeDefaultDescription
params.subject.otherNamesstring-Middle names
params.subject.dateOfBirthDate-Date of birth (structured object: {year, month, day})
params.subject.yearOfBirthuint32-Year of birth (alternative to full date)
params.addressAddress-Residential address (if known)
params.enableOngoingMonitoringboolfalseContinuous AML screening monitoring
params.requireAddressVerificationboolfalseElectronic address matching & verification
params.requireCcjInsolvencyboolfalseSurface CCJs or insolvency indicators on an individual (UK addresses only)
params.internationalAddressVerificationConsentboolfalseRequired for non-UK addresses if address verification is enabled

Complete Example

Create Check Request

curl -X POST "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams/{team_id}/checks" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"displayName": "Identity verification for Jane Smith",
"clientReference": "client-12345",
"template": "checkTemplates/identity-verification-check-v1-0-0",
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.IdentityVerificationCheckParams",
"subject": {
"givenName": "Jane",
"familyName": "Smith",
"email": "jane.smith@example.com",
"dateOfBirth": {
"year": 1990,
"month": 6,
"day": 15
}
},
"address": {
"buildingNumber": "123",
"street": "High Street",
"locality": "London",
"postalCode": "SW1A 1AA",
"countryCode": "GBR"
},
"enableOngoingMonitoring": true,
"requireAddressVerification": true
}
}'

Note: The endpoint includes the parent (team) in the URL path. Replace {org_id} and {team_id} with your actual organization and team IDs.

Response

{
"name": "organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL/checks/eaa99a49-7c7c-43e0-a929-ec2dddec8a85",
"displayName": "Identity verification for Jane Smith",
"clientReference": "client-12345",
"state": "ACTIVE",
"createTime": "2026-03-06T14:06:59.758655Z",
"updateTime": null,
"template": "checkTemplates/identity-verification-check-v1-0-0",
"params": { ... },
"relatedSubjects": [ ... ],
"creator": "partners/thirdfort/integrations/4",
"ongoingMonitoring": {
"enabled": true,
"activeUntil": null
}
}

Summary Response

{
"name": "organizations/.../teams/.../checks/.../checkSummary",
"createTime": "2026-03-06T14:07:00.537001Z",
"payload": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.IdentityVerificationCheckSummary",
"overallRecommendation": {
"recommendation": "CLEAR",
"description": "No concerning issues found"
},
"identityDocumentCheckResult": { ... },
"livenessCheckResult": { ... },
"screeningCheckResult": { ... },
"addressVerificationCheckResult": { ... },
"ccjInsolvencyCheckResult": null,
"providedSubjectData": { ... }
},
"sourceFindings": [ ... ],
"reportUrl": "https://files.thirdfort.dev/client/downloads/objects/6ff46f10-ae87-42e6-8601-1f0c32ed5ba6",
"summaryReportUrl": "https://files.thirdfort.dev/client/downloads/objects/8df632f9-e3f9-4e9e-88aa-ca449debf3b8"
}

Result Fields

FieldDescription
payload.overallRecommendationOverall check recommendation object with recommendation and description
payload.identityDocumentCheckResultDocument verification results - always included
payload.livenessCheckResultLiveness detection results - always included
payload.screeningCheckResultAML screening results (sanctions/PEP) - always included
payload.addressVerificationCheckResultAddress verification results - only if requireAddressVerification: true
payload.ccjInsolvencyCheckResultCCJ/Insolvency results - only if requireCcjInsolvency: true and UK address
payload.providedSubjectDataEcho of the subject data you provided
reportUrlDownload link for full PDF report (top-level field)
summaryReportUrlDownload link for summary PDF report (top-level field)
sourceFindingsArray of finding resource names that contributed to this summary

Recommendation Values

  • CLEAR: No concerning issues found - proceed with confidence
  • CONSIDER: Anomalies detected that may be explainable - review findings
  • FAIL: Serious anomalies detected, unlikely explainable - high risk

Monitoring Check Progress

Identity verification checks require consumer interaction and may take several minutes to complete. You can monitor progress using either notifications (recommended) or check status polling.

Receive real-time updates when the check completes or status changes.

Polling for Notifications

Poll the notifications endpoint to retrieve updates:

GET /v1/organizations/{organization}/notifications?page_size=25

Example: Poll for check completion

import requests
import time

def poll_for_check_completion(organization, check_name, access_token, timeout_seconds=600):
"""
Poll for check completion notification.

Args:
organization: Organization ID (e.g., 'acme-corp')
check_name: Full check resource name
access_token: OAuth access token
timeout_seconds: Maximum time to wait (default: 10 minutes)

Returns:
Notification dict when check completes, or None if timeout
"""
base_url = "https://api.thirdfort.dev/client/api"
headers = {"Authorization": f"Bearer {access_token}"}

start_time = time.time()
cursor = None

while time.time() - start_time < timeout_seconds:
# Build request URL
url = f"{base_url}/v1/organizations/{organization}/notifications"
params = {"page_size": 25}

if cursor:
params["page_token"] = cursor

# Poll for notifications
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()

data = response.json()
notifications = data.get("notifications", [])

# Check for check completion notification
for notification in notifications:
if notification["type"] == "notification.client.check_complete.v1":
payload = notification["payload"]
if payload.get("check") == check_name:
print(f"Check completed with recommendation: {payload['recommendation']}")
return notification

# Update cursor for next poll
if "nextPageToken" in data:
cursor = data["nextPageToken"]

# Wait before next poll
time.sleep(30)

print("Timeout waiting for check completion")
return None

# Usage
notification = poll_for_check_completion(
organization="acme-corp",
check_name="organizations/acme-corp/teams/default/checks/01JRA3XYZ789",
access_token="your_access_token"
)

if notification:
# Check completed - retrieve results
check_name = notification["payload"]["check"]
# ... fetch check summary and findings

Notification Types:

  • notification.client.check_complete.v1 - Check has completed processing
  • notification.client.report_generated.v1 - Report has been generated (e.g., after finding review)

Best Practices:

  • Store the nextPageToken between polls to avoid missing notifications
  • Poll every 30-60 seconds (avoid more frequent polling)
  • Use notification ID for deduplication
  • Filter by notification type to reduce processing

For comprehensive polling implementation details, see the Polling for Notifications guide.

Webhooks

For real-time push delivery, Thirdfort can configure webhook endpoints to receive notifications as they occur. Contact your Thirdfort account manager or email api-support@thirdfort.com to set up webhook delivery.

Option 2: Check Status Polling

Alternatively, poll the check resource directly to monitor state changes:

# Poll check status every 30 seconds
curl -X GET "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams/{team_id}/checks/{check_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Check States:

  • ACTIVE - Check is processing or waiting for consumer
  • INACTIVE - Check has completed, results available
  • CANCELLED - Check was cancelled
  • DELETED - Check was soft-deleted

When to use check status polling:

  • You only need to monitor a single check
  • You don't need to track other events (report generation, monitoring hits)
  • You prefer simpler implementation

When to use notification polling:

  • You need to monitor multiple checks
  • You want to track all events (completion, reports, monitoring)
  • You want more efficient API usage

Common Configurations

Basic Identity Verification

Minimal configuration for identity verification:

{
"displayName": "Identity verification for Jane Smith",
"clientReference": "client-12345",
"template": "checkTemplates/identity-verification-check-v1-0-0",
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.IdentityVerificationCheckParams",
"subject": {
"givenName": "Jane",
"familyName": "Smith",
"email": "jane.smith@example.com"
}
}
}

With Ongoing Monitoring

Enable continuous sanctions monitoring:

{
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.IdentityVerificationCheckParams",
"subject": { ... },
"enableOngoingMonitoring": true
}
}

With Address Verification

Verify the provided or consumer-entered address:

{
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.IdentityVerificationCheckParams",
"subject": { ... },
"address": {
"buildingNumber": "123",
"street": "High Street",
"locality": "London",
"postalCode": "SW1A 1AA",
"countryCode": "GBR"
},
"requireAddressVerification": true
}
}

Best Practices

Provide Known Data

If you already have the consumer's information, provide it in the check parameters:

{
"subject": {
"givenName": "Jane",
"familyName": "Smith",
"email": "jane.smith@example.com",
"dateOfBirth": {
"year": 1990,
"month": 6,
"day": 15
}
},
"address": { ... }
}

This pre-fills the mobile app and improves the consumer experience.

Consumer Notifications

  • Provide either email or phoneNumber (or both)
  • Email notifications include a magic link to open the app
  • SMS notifications include a link to download the app
  • Consumers can complete verification on any device

Handling Incomplete Checks

If a consumer doesn't complete verification:

  • Check remains in ACTIVE state
  • You can cancel the check via API
  • You can create a new check for the same consumer

Troubleshooting

Common Issues

Consumer didn't receive notification

  • Verify email/phone number is correct
  • Check spam folder (for email)
  • Resend notification via API (if supported)

Check stuck in ACTIVE state

  • Consumer may not have completed all tasks
  • Check consumer's progress via mobile app
  • Consider cancelling and creating new check

400 Bad Request - "field required"

  • Ensure displayName and clientReference are included
  • Verify @type field is present in params
  • Check that dateOfBirth uses structured object format (not string)
  • Ensure either email or phoneNumber is provided

404 Not Found

  • Verify the endpoint includes parent in URL: /v1/{parent}/checks
  • Check that organization and team IDs are correct
  • Ensure endpoint is /checkSummary not /summary