Integrate TrueGate identity verification into your application.
All API requests require a Bearer token. Get your API key from Settings in the dashboard.
curl -H "Authorization: Bearer tg_live_your_api_key" \ https://www.truegate.io/api/v1/verification
Create a verification
Your backend calls POST /api/v1/verification with an API key. You receive a URL to redirect your user to.
Redirect user
Send your user to the url returned. They complete document capture and selfie on TrueGate.
Receive result
TrueGate sends a POST to your callback_url with the result. The user is also redirected to your redirect_url with query params.
Query anytime
You can also poll GET /api/v1/verification/{token} to check the status at any time.
| Parameter | Type | Required | Description |
|---|---|---|---|
| vendor_data | string | No | Your internal reference (e.g. user ID) |
| callback_url | string | No | URL to receive webhook POST with result |
| redirect_url | string | No | URL to redirect user after verification |
| verification_type | string | No | "basic" (default) |
curl -X POST https://www.truegate.io/api/v1/verification \
-H "Authorization: Bearer tg_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"vendor_data": "user-456",
"callback_url": "https://yourapp.com/api/truegate-webhook",
"redirect_url": "https://yourapp.com/onboarding/complete"
}'{
"token": "a1b2c3d4e5f6...",
"url": "https://www.truegate.io/verify/a1b2c3d4e5f6...",
"result_url": "https://www.truegate.io/verify/a1b2c3d4e5f6.../result",
"session_id": 42,
"expires_at": "2026-03-22T17:00:00.000Z"
}curl https://www.truegate.io/api/v1/verification/a1b2c3d4e5f6 \ -H "Authorization: Bearer tg_live_your_api_key"
{
"token": "a1b2c3d4e5f6...",
"status": "approved",
"final_decision": "approved",
"verification_type": "basic",
// Personal info
"extracted_name": "John Doe",
"extracted_dob": "1990-01-15",
"extracted_nationality": "Panama",
"gender": "M",
"place_of_birth": "Panama City",
"address": "Av. Balboa 45, Panama City",
// Document
"extracted_document_type": "Identity Card",
"extracted_document_number": "8-123-456",
"issuing_country": "Panama",
"issuing_country_code": "PAN",
"issuing_subdivision": "Panama Province",
"document_issue_date": "2020-05-10",
"document_expiry_date": "2030-05-10",
"document_status": "VALID",
"document_quality_score": 92,
// Individual document checks — "passed" | "failed" | "not_checked"
"document_checks": {
"template": "passed",
"alteration": "passed",
"mrz": "passed",
"age": "passed",
"duplicate": "passed",
"expiry": "passed",
"data_consistency": "passed",
"photo_manipulation": "passed"
},
// Signed image URLs (5 min expiry) — download and re-host if you
// need durable copies. provider_* are Didit-hosted fallbacks.
"images": {
"document_front": "https://<supabase>/...?token=...",
"document_back": "https://<supabase>/...?token=...",
"selfie": "https://<supabase>/...?token=...",
"provider_front": null,
"provider_back": null,
"provider_portrait": null,
"provider_selfie": null
},
// Biometric
"identity_verified": true,
"face_match_score": 96.37,
"face_match_status": "MATCH",
"liveness_passed": true,
"liveness_score": 0.98,
// Compliance
"sanctions_match": false,
"rejection_reasons": [],
// Device fingerprint of the client that took the photos
"device": {
"ip": "200.24.60.10",
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_6 like Mac OS X) …",
"browser": "Safari",
"browser_version": "17.6",
"os": "iOS",
"os_version": "17.6",
"device_type": "mobile"
},
"result_url": "https://www.truegate.io/verify/a1b2c3d4e5f6.../result",
"created_at": "2026-09-29T12:34:56.000Z",
"updated_at": "2026-09-29T12:35:12.000Z"
}address, issuing_subdivision, place_of_birth — OCR-extracted from the document. Empty when the document doesn't carry the value. For LATAM national IDs, the address usually lives on the back and only populates when the reverse side was captured.document_checks — each key is one control Didit runs on the document. passed when no matching warning was raised, failed when Didit flagged that control, not_checked when Didit didn't evaluate it for that document type. In particular, mrz only resolves to passed/failed for two-sided documents where TrueGate captured the reverse; for passports (biodata page) it can be evaluated from the front alone.images.document_front / document_back / selfie — signed URLs against TrueGate storage, valid 5 minutes from the API call. document_back is null when the visitor picked Passport in the capture flow (single-page document) and populated for national ID / driver's license / residence permit. Download and re-host if you need durable copies.device — parsed at submit time from the phone/laptop that took the photos, not the org that owns the session. null for legacy verifications that predate the capture.When an end user opens the url returned by POST /api/v1/verification, the hosted flow now asks them to pick the document type before the camera opens, and captures only the photos that document actually needs:
This means the OCR pass and the fraud checks that require the reverse side (MRZ validation, address extraction, signature check, front↔back data consistency) run automatically for two-sided documents. No integration change is needed on your side — the result JSON is the same shape whether or not the visitor captured a back image; the affected fields (address, images.document_back, document_checks.mrz) simply populate when the reverse side was part of the capture.
The dashboard History → Detail modal and the downloadable PDF report show both front and back thumbnails side by side when the reverse was captured.
curl "https://www.truegate.io/api/v1/verification?page=1" \ -H "Authorization: Bearer tg_live_your_api_key"
Screen a company directly via the API. No verification link needed -- the result is returned immediately.
| Parameter | Type | Required | Description |
|---|---|---|---|
| company_name | string | Yes | Name of the company to screen |
| country | string | No | Country code (e.g. PA, US) |
| registration_number | string | No | Company registration number |
| vendor_data | string | No | Your internal reference |
| callback_url | string | No | URL to receive webhook POST with result |
curl -X POST https://www.truegate.io/api/v1/business-screening \
-H "Authorization: Bearer tg_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"company_name": "Acme Corp",
"country": "PA",
"registration_number": "12345",
"vendor_data": "company-ref-456",
"callback_url": "https://yourapp.com/webhooks/truegate"
}'{
"token": "abc123...",
"vendor_data": "company-ref-456",
"result_url": "https://www.truegate.io/verify/abc123.../result",
"company_name": "Acme Corp",
"country": "PA",
"status": "approved",
"sanctions_match": false,
"aml": {
"status": "Approved",
"total_hits": 0,
"score": null,
"hits": []
},
"news": {
"total_articles": 5,
"risk_articles": 0,
"articles": [{ "title": "...", "source": "...", "url": "...", "published_at": "..." }],
"risk": []
},
"registry": [],
"created_at": "2026-07-22T..."
}Cost: $0.50 per screening. Includes: sanctions/watchlist check (1,300+ lists), adverse media, Google News risk analysis.
Validate a phone number with carrier lookup, identity match, SIM swap detection, reassigned number check, and SMS OTP -- all in a single API call. Results are returned directly.
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone_number | string | Yes | Phone number in E.164 format (e.g. +15551234567) |
| full_name | string | No | Name to match against phone owner records |
| vendor_data | string | No | Your internal reference |
| callback_url | string | No | URL to receive webhook POST with result |
curl -X POST https://www.truegate.io/api/v1/phone-validation \
-H "Authorization: Bearer tg_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+15551234567",
"full_name": "John Doe",
"vendor_data": "user-456"
}'{
"token": "ph_abc123...",
"status": "approved",
"phone_number": "+15551234567",
"carrier": {
"name": "T-Mobile",
"type": "mobile",
"country": "US"
},
"identity_match": {
"match": true,
"score": 0.95,
"registered_name": "John A Doe"
},
"sim_swap": {
"detected": false,
"last_swap_date": null,
"risk": "low"
},
"reassigned": {
"detected": false,
"last_assignment_date": "2019-03-15"
},
"sms_verified": true,
"risk_level": "low",
"created_at": "2026-07-24T..."
}Cost: $0.35 per validation. Includes: carrier lookup, identity match, SIM swap detection, reassigned number check, and SMS OTP.
Run a standalone sanctions/AML check by name without requiring identity verification.
| Parameter | Type | Required | Description |
|---|---|---|---|
| full_name | string | Yes | Full name to screen (min 2 characters) |
| date_of_birth | string | No | Date of birth (YYYY-MM-DD) |
| nationality | string | No | Country code (e.g. PA, US) |
| check_type | string | Yes | "registration", "withdrawal", or "batch" |
curl -X POST https://www.truegate.io/api/compliance/check \
-H "Authorization: Bearer tg_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"full_name": "John Doe",
"date_of_birth": "1990-01-15",
"nationality": "PA",
"check_type": "registration"
}'{
"check_id": 99,
"match_found": false,
"highest_match_score": 0.0,
"risk_level": "low",
"matches": [],
"processing_time_ms": 245
}Webhook callback
When a verification completes, TrueGate sends a POST to your callback_url:
{
"event": "verification.completed",
"token": "a1b2c3d4e5f6...",
"vendor_data": "user-456",
"status": "approved",
"final_decision": "approved",
// Personal info
"extracted_name": "John Doe",
"extracted_dob": "1990-01-15",
"extracted_nationality": "Panama",
"gender": "M",
"place_of_birth": "Panama City",
"address": "Av. Balboa 45, Panama City",
// Document
"extracted_document_type": "Identity Card",
"extracted_document_number": "8-123-456",
"issuing_country": "Panama",
"issuing_country_code": "PAN",
"issuing_subdivision": "Panama Province",
"document_issue_date": "2020-05-10",
"document_expiry_date": "2030-05-10",
"document_quality_score": 92,
"document_checks": {
"template": "passed", "alteration": "passed", "mrz": "passed",
"age": "passed", "duplicate": "passed", "expiry": "passed",
"data_consistency": "passed", "photo_manipulation": "passed"
},
// Images — signed URLs, 5 min expiry
"images": {
"document_front": "https://<supabase>/...?token=...",
"document_back": "https://<supabase>/...?token=...",
"selfie": "https://<supabase>/...?token=..."
},
// Biometric
"identity_verified": true,
"face_match_score": 96.37,
"face_match_status": "MATCH",
"liveness_passed": true,
"liveness_score": 0.98,
// Compliance
"sanctions_match": false,
"rejection_reasons": [],
// Only populated when the session ran a civil-registry check
"database_validation": null,
// Device fingerprint of the client that took the photos
"device": {
"ip": "200.24.60.10",
"user_agent": "Mozilla/5.0 ...",
"browser": "Safari",
"browser_version": "17.6",
"os": "iOS",
"os_version": "17.6",
"device_type": "mobile"
},
"timestamp": "2026-03-21T18:30:00.000Z"
}User redirect
After verification, the user is automatically redirected to your redirect_url with query parameters:
https://yourapp.com/onboarding/complete?token=a1b2c3d4e5f6&status=approved&decision=approved
You can read the decision query param to immediately show the appropriate screen, then verify the result server-side via the API.
Every verification returns a result_url. It's a merchant-facing page — visiting it as the merchant that owns the verification (signed in to the TrueGate dashboard) or as a TrueGate super admin renders the full report with every extracted field, the captured images, the government DB comparison and a download button for the PDF. Any other viewer, including the person who was verified, gets a plain "verification complete" acknowledgement with no PII.
https://www.truegate.io/verify/{token}/resultUse result_urlas the merchant's own review link — share it with your compliance team or embed it in your internal dashboard. For a downloadable PDF of the same report, call GET /api/v1/verification/{token}/pdf with your API key.
TrueGate supports multiple verification types. Specify the type when creating a verification session via the verification_type field.
| Type | Description | Price | |
|---|---|---|---|
| basic | ID + liveness + face match + sanctions | $0.75 | |
| advanced | Basic + 1000+ AML lists + PEP + adverse media + IP | $1.25 | |
| business_aml | Company sanctions + adverse media + news | $0.50 | |
| email_verification | Email OTP | $0.25 | |
| phone_verification | Phone OTP (WhatsApp) | $0.25 | |
| phone_antifraud | Carrier lookup + identity match + SIM swap + reassigned number + SMS OTP | $0.35 | |
| database_validation | Gov database, 18 LATAM countries | $1.50 | |
| custom | Mix & match steps | per step |
Verification statuses
| Status | Description | ||
|---|---|---|---|
| pending | Session created, waiting for user | ||
| processing | User submitted, verification in progress | ||
| approved | All checks passed | ||
| rejected | One or more checks failed | ||
| expired | Session expired (24 hours) |
Error codes
| HTTP | Code | Description | |
|---|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key | |
| 402 | INSUFFICIENT_BALANCE | Not enough balance. Top up in dashboard | |
| 403 | FORBIDDEN | Verification belongs to another organization | |
| 404 | NOT_FOUND | Verification not found | |
| 422 | VALIDATION_ERROR | Invalid request parameters |
TrueGate charges per verification based on the type selected.
| Verification Type | Price | Includes | |
|---|---|---|---|
| basic | $0.75 | ID verification, passive liveness, face match, sanctions screening (OFAC, UN, EU) | |
| advanced | $1.25 | Everything in basic + 1000+ AML lists, PEP screening, adverse media, IP analysis | |
| business_aml | $0.50 | Company sanctions, adverse media, Google News risk analysis (1,300+ lists) | |
| email_verification | $0.25 | Email OTP verification | |
| phone_verification | $0.25 | Phone OTP via WhatsApp | |
| phone_antifraud | $0.35 | Carrier lookup + identity match + SIM swap + reassigned number + SMS OTP | |
| database_validation | $1.50 | Government database validation, 18 LATAM countries | |
| custom | per step | Mix & match individual verification steps |
No minimums. Top up anytime in Settings. Compliance checks via POST /api/compliance/check are included at no extra cost.
TrueGate provides native SDKs for mobile apps. Each SDK opens the verification flow in a branded WebView with native callbacks.
@truegate/react-native-sdknpm install @truegate/react-native-sdk react-native-webview
import { TrueGateVerify } from '@truegate/react-native-sdk';
<TrueGateVerify
url={verificationUrl}
visible={showVerify}
onComplete={(result) => {
if (result.status === 'approved') { /* verified */ }
}}
onCancel={() => setShowVerify(false)}
/>View on GitHub →TrueGateSDK// Swift Package Manager
.package(url: "https://github.com/eflorezlabequis/truegate", from: "1.0.0")
import TrueGateSDK
let truegate = TrueGate(apiKey: "tg_live_...")
truegate.presentVerification(from: self, url: verificationUrl) { result in
switch result {
case .success(let r): print(r.isApproved)
case .failure(let e): print(e)
}
}View on GitHub →io.truegate.sdk// build.gradle
implementation("io.truegate:sdk:1.0.0")
val truegate = TrueGate("tg_live_...")
truegate.presentVerification(this, verificationUrl, object : TrueGateCallback {
override fun onComplete(result: TrueGateResult) {
if (result.isApproved) { /* verified */ }
}
override fun onCancelled() { }
override fun onError(error: Exception) { }
})View on GitHub →TrueGate API v1 — www.truegate.io