API Reference

Integrate TrueGate identity verification into your application.

Download AI Integration GuideGive this file to Claude Code, ChatGPT, or any AI assistant to integrate TrueGate in minutes.

Authentication

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

Integration Flow

1

Create a verification

Your backend calls POST /api/v1/verification with an API key. You receive a URL to redirect your user to.

2

Redirect user

Send your user to the url returned. They complete document capture and selfie on TrueGate.

3

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.

4

Query anytime

You can also poll GET /api/v1/verification/{token} to check the status at any time.

Create Verification

POST/api/v1/verification

Request body

ParameterTypeRequiredDescription
reference_idstringNoYour internal reference (e.g. user ID)
callback_urlstringNoURL to receive webhook POST with result
redirect_urlstringNoURL to redirect user after verification
verification_typestringNo"basic" (default)

Example

curl -X POST https://www.truegate.io/api/v1/verification \
  -H "Authorization: Bearer tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "reference_id": "user-456",
    "callback_url": "https://yourapp.com/api/truegate-webhook",
    "redirect_url": "https://yourapp.com/onboarding/complete"
  }'

Response

{
  "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"
}

Get Verification Result

GET/api/v1/verification/{token}
curl https://www.truegate.io/api/v1/verification/a1b2c3d4e5f6 \
  -H "Authorization: Bearer tg_live_your_api_key"

Response

{
  "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.
  "images": {
    "document_front": "https://<storage>/...?token=...",
    "document_back": "https://<storage>/...?token=...",
    "selfie": "https://<storage>/...?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": [],

  // 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"
}

Field notes

  • 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 of TrueGate's document controls. passed when no matching warning was raised, failed when the control flagged the document, not_checked when the control doesn't apply to 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.

Hosted capture flow

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:

  • National ID / Cedula — front + back. MRZ, address and anti-tampering patterns live on the back.
  • Driver's license — front + back.
  • Residence permit / Foreigner ID — front + back.
  • Passport — biodata page only. Asking for a back photo would add friction with no additional signal.

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.

List Verifications

GET/api/v1/verification?page=1&pageSize=20
curl "https://www.truegate.io/api/v1/verification?page=1" \
  -H "Authorization: Bearer tg_live_your_api_key"

Business Screening

Screen a company directly via the API. No verification link needed -- the result is returned immediately.

POST/api/v1/business-screening

Request body

ParameterTypeRequiredDescription
company_namestringYesName of the company to screen
countrystringNoCountry code (e.g. PA, US)
registration_numberstringNoCompany registration number
reference_idstringNoYour internal reference
callback_urlstringNoURL to receive webhook POST with result

Example

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",
    "reference_id": "company-ref-456",
    "callback_url": "https://yourapp.com/webhooks/truegate"
  }'

Response

{
  "token": "abc123...",
  "reference_id": "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.

Phone Validation & Antifraud

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.

POST/api/v1/phone-validation

Request body

ParameterTypeRequiredDescription
phone_numberstringYesPhone number in E.164 format (e.g. +15551234567)
full_namestringNoName to match against phone owner records
reference_idstringNoYour internal reference
callback_urlstringNoURL to receive webhook POST with result

Example

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",
    "reference_id": "user-456"
  }'

Response

{
  "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.

Government Database Validation

Validate a national ID number directly against the country's civil registry — the Panamanian Tribunal Electoral, Venezuela's SAIME, Argentina's RENAPER, Colombia's Registraduría, Mexico's CURP registry, Brazil's CPF, and so on. Results come back synchronously; no hosted link needed.

Use this when you already hold the person's cédula / DNI number — e.g. your sign-up form captured it, your partner API sent it, or you're running a batch over an existing list. For a flow where the end-user themselves presents their document (OCR + selfie), use verification_type: "database_validation" on the hosted link instead.

POST/api/v1/database-validation

Request body

ParameterTypeRequiredDescription
issuing_countrystringYesISO 3166 alpha-3 country code (PAN, VEN, COL, …)
identification_numberstringYesNational ID / cédula / DNI as it appears on the document
first_namestringNoImproves name match quality
last_namestringNoImproves name match quality
date_of_birthstringVariesYYYY-MM-DD. Required for BOL, SLV, URY; optional elsewhere
genderstringVaries&quot;M&quot; or &quot;F&quot;. Required for ARG
date_of_issuestringVariesYYYY-MM-DD. Required for COL (on back of cédula)
document_typestringVariesRequired for ESP
expiration_datestringVariesYYYY-MM-DD. Required for ESP
selfiestring (base64)VariesData URL. Required for ARG and PAN (biometric match)
reference_idstringNoYour internal reference

Per-country required fields

Discover these at runtime by calling GET /api/v1/database-validation — returns the full list with required_fields, requires_selfie and notes per country. When a required field is missing the endpoint responds with MISSING_REQUIRED_FIELDSand names what's missing — no credit is deducted. Current matrix (18 countries supported):

ParameterTypeRequiredDescription
ARG — Argentinaidentification_number, gender, selfie
BOL — Boliviaidentification_number, date_of_birth
BRA — Brazilidentification_number
CHL — Chileidentification_number
COL — Colombiaidentification_number, date_of_issue
CRI — Costa Ricaidentification_number
DOM — Dominican Republicidentification_number
ECU — Ecuadoridentification_number
ESP — Spainidentification_number, document_type, expiration_date
GTM — Guatemalaidentification_number
HND — Hondurasidentification_number
MEX — Mexicoidentification_number
PAN — Panamaidentification_number, selfie (biometric SIB Plus — returns full Tribunal Electoral record)
PER — Peruidentification_number
PRY — Paraguayidentification_number
SLV — El Salvadoridentification_number, date_of_birth
URY — Uruguayidentification_number, date_of_birth
VEN — Venezuelaidentification_number

Panamá — example (requires selfie, returns full Tribunal Electoral record)

curl -X POST https://www.truegate.io/api/v1/database-validation \
  -H "Authorization: Bearer tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "issuing_country": "PAN",
    "identification_number": "8-123-456",
    "selfie": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
    "reference_id": "user-456"
  }'

Argentina — example (RENAPER requires selfie + gender)

curl -X POST https://www.truegate.io/api/v1/database-validation \
  -H "Authorization: Bearer tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "issuing_country": "ARG",
    "identification_number": "12345678",
    "gender": "M",
    "first_name": "María",
    "last_name": "González",
    "date_of_birth": "1990-03-15",
    "selfie": "data:image/jpeg;base64,...",
    "reference_id": "user-789"
  }'

Colombia — example (Registraduría requires date_of_issue)

curl -X POST https://www.truegate.io/api/v1/database-validation \
  -H "Authorization: Bearer tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "issuing_country": "COL",
    "identification_number": "1012345678",
    "date_of_issue": "2015-07-20",
    "first_name": "Carlos",
    "last_name": "Rodríguez",
    "date_of_birth": "1985-05-20",
    "reference_id": "user-456"
  }'

Venezuela — example (identification_number only)

curl -X POST https://www.truegate.io/api/v1/database-validation \
  -H "Authorization: Bearer tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "issuing_country": "VEN",
    "identification_number": "V-12345678",
    "first_name": "María",
    "last_name": "González",
    "date_of_birth": "1990-03-15",
    "reference_id": "user-789"
  }'

Response

{
  "request_id": "...",
  "comparison": "exact",
  "status": "Approved",
  "country": "PAN",
  "country_name": "Panama",

  // Registry-returned PII — authoritative civil-registry record
  "full_name": "Juan Carlos Pérez",
  "first_name": "Juan Carlos",
  "last_name": "Pérez",
  "date_of_birth": "1985-05-20",
  "nationality": "PAN",
  "gender": "M",
  "address": "Av. Balboa 45",
  "document_type": "Cedula",
  "document_number": "8-123-4567",

  // Per-field comparison between what you sent and what the registry has
  "registry_fields": {
    "firstName": "Juan Carlos",
    "lastName": "Pérez",
    "fullName": "Juan Carlos Pérez",
    "byField": {
      "first_name": { "input": "Juan", "returned": "Juan Carlos", "comparison": "partial" },
      "last_name":  { "input": "Pérez", "returned": "Pérez", "comparison": "exact" }
    }
  },

  "validations": [
    { "field": "first_name", "input_value": "Juan", "returned_value": "Juan Carlos", "comparison": "partial" }
  ],
  "warnings": []
}

comparison values: exact (every sent field matches the registry), partial (ID valid but some fields differ — e.g. you sent "Juan" but the registry has "Juan Carlos"), none (ID not found in the registry).

The top-level full_name / date_of_birth / address carry what the civil registry has on file — often richer than what you sent. Use registry_fields.byField for a per-field audit UI.

Cost: $1.50 per lookup. Requires the database_validation workflow to be enabled on your organization — toggle it in Dashboard → Workflows.

Compliance Check

Run a standalone sanctions/AML check by name without requiring identity verification.

POST/api/compliance/check

Request body

ParameterTypeRequiredDescription
full_namestringYesFull name to screen (min 2 characters)
date_of_birthstringNoDate of birth (YYYY-MM-DD)
nationalitystringNoCountry code (e.g. PA, US)
check_typestringYes"registration", "withdrawal", or "batch"

Example

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"
  }'

Response

{
  "check_id": 99,
  "match_found": false,
  "highest_match_score": 0.0,
  "risk_level": "low",
  "matches": [],
  "processing_time_ms": 245
}

Webhooks

Webhook callback

When a verification completes, TrueGate sends a POST to your callback_url:

{
  "event": "verification.completed",
  "token": "a1b2c3d4e5f6...",
  "reference_id": "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.

Result Page

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.

Example URL

https://www.truegate.io/verify/{token}/result

Use 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.

Verification Types

TrueGate supports multiple verification types. Specify the type when creating a verification session via the verification_type field.

TypeDescriptionPrice
basicID + liveness + face match + sanctions$0.75
advancedBasic + 1000+ AML lists + PEP + adverse media + IP$1.25
business_amlCompany sanctions + adverse media + news$0.50
email_verificationEmail OTP$0.25
phone_verificationPhone OTP (WhatsApp)$0.25
phone_antifraudCarrier lookup + identity match + SIM swap + reassigned number + SMS OTP$0.35
database_validationGov database, 18 LATAM countries$1.50
customMix & match stepsper step

Statuses & Errors

Verification statuses

StatusDescription
pendingSession created, waiting for user
processingUser submitted, verification in progress
approvedAll checks passed
rejectedOne or more checks failed
expiredSession expired (24 hours)

Error codes

HTTPCodeDescription
401UNAUTHORIZEDMissing or invalid API key
402INSUFFICIENT_BALANCENot enough balance. Top up in dashboard
403FORBIDDENVerification belongs to another organization
404NOT_FOUNDVerification not found
422VALIDATION_ERRORInvalid request parameters

Pricing

TrueGate charges per verification based on the type selected.

Verification TypePriceIncludes
basic$0.75ID verification, passive liveness, face match, sanctions screening (OFAC, UN, EU)
advanced$1.25Everything in basic + 1000+ AML lists, PEP screening, adverse media, IP analysis
business_aml$0.50Company sanctions, adverse media, Google News risk analysis (1,300+ lists)
email_verification$0.25Email OTP verification
phone_verification$0.25Phone OTP via WhatsApp
phone_antifraud$0.35Carrier lookup + identity match + SIM swap + reassigned number + SMS OTP
database_validation$1.50Government database validation, 18 LATAM countries
customper stepMix & match individual verification steps

No minimums. Top up anytime in Settings. Compliance checks via POST /api/compliance/check are included at no extra cost.

SDKs & Mobile Integration

TrueGate provides native SDKs for mobile apps. Each SDK opens the verification flow in a branded WebView with native callbacks.

React Native

@truegate/react-native-sdk
npm 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 →

iOS (Swift)

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 →

Android (Kotlin)

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