Verification Statuses
This guide explains the status lifecycle for applicants, documents, and screening checks in TrustGate. Understanding these statuses helps you build effective verification flows and handle edge cases.
Applicant Statuses
Status Diagram
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
‚Üì ‚Üì
↓ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎ ↓
↓ ↓ PENDING ↓ↀↀ>↓ IN_PROGRESS ↓ↀↀ>↓ REVIEW ↓ ↓
↓ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎ ↓
‚Üì ‚Üì ‚Üì
↓ ↔ↀↀↀↀↀↀↀↀↀↀↀ↏ↀↀↀↀↀↀↀↀ← ↓
‚Üì v v ‚Üì
↓ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ↓
‚Üì ‚Üì APPROVED ‚Üì ‚Üì REJECTED ‚Üì ‚Üì
↓ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ↓
‚Üì ‚Üì
↓ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ↓
‚Üì (any status)‚ÜÄ>‚Üì WITHDRAWN ‚Üì ‚Üì
↓ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ↓
‚Üì ‚Üì
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Status Definitions
| Status | Description | Typical Duration | Next Actions |
|---|---|---|---|
pending | Applicant created, awaiting verification steps | Minutes to hours | Upload documents, complete steps |
in_progress | Verification steps being completed | Hours to days | Complete remaining steps |
review | All steps complete, awaiting human review | Hours to days | Reviewer decision |
approved | Verification successful, applicant approved | Terminal | Grant access, onboard |
rejected | Verification failed, applicant rejected | Terminal | Appeal process (optional) |
withdrawn | Applicant withdrew application | Terminal | Re-apply (if allowed) |
Status Transitions
Pending → In Progress
Triggered when:
- First document uploaded
- First verification step started
- Screening initiated
# Example: First document upload triggers status change
document = upload_document(applicant_id, "passport", file)
# Applicant status automatically updates to "in_progress"
In Progress → Review
Triggered when:
- All required workflow steps completed
- Automatic review conditions not met (risk score, hits)
# Example: Check if ready for review
applicant = get_applicant(applicant_id)
steps_complete = all(s["status"] == "complete" for s in applicant["steps"])
if steps_complete:
# Status automatically moves to "review" if screening has hits
# or risk score exceeds auto-approve threshold
Review → Approved/Rejected
Triggered when:
- Reviewer makes decision via dashboard or API
# Approve applicant
response = requests.post(
f"{BASE_URL}/applicants/{applicant_id}/review",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"decision": "approved"},
)
# Reject applicant
response = requests.post(
f"{BASE_URL}/applicants/{applicant_id}/review",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"decision": "rejected"},
)
Auto-Approval (Pending/In Progress → Approved)
If configured, low-risk applicants can be auto-approved:
Conditions for auto-approval:
‚úì All required steps completed
‚úì No screening hits
‚úì Risk score ‚â§ auto_approve_threshold (default: 30)
‚úì No risk flags
Risk Levels and Routing
| Risk Score | Risk Level | Default Routing |
|---|---|---|
| 0-30 | Low | Auto-approve (if enabled) |
| 31-60 | Medium | Queue for review |
| 61-80 | High | Priority review |
| 81-100 | Critical | Escalate to senior reviewer |
Document Statuses
Status Diagram
ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ
↓ PENDING ↓ↀↀ>↓ PROCESSING ↓ↀ↏ↀ>↓ VERIFIED ↓
ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ
‚Üì
v
ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ
‚Üì REJECTED ‚Üì
ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ
‚Üì
v
ⅎⅎⅎⅎⅎⅎⅎⅎⅎ
‚Üì EXPIRED ‚Üì (Post-verification, if expiry date passed)
ⅎⅎⅎⅎⅎⅎⅎⅎⅎ
Status Definitions
| Status | Description | Duration |
|---|---|---|
pending | Document uploaded, awaiting processing | Seconds |
processing | OCR and verification in progress | 2-10 seconds |
verified | Successfully verified, data extracted | Terminal (may expire) |
rejected | Verification failed | Terminal |
expired | Document expiry date has passed | Terminal |
Rejection Reasons
| Reason | Description | User Action |
|---|---|---|
image_quality_low | Image too blurry/low resolution | Retake photo |
document_expired | Document past expiry date | Upload valid document |
tampering_suspected | Signs of digital manipulation | Upload unaltered document |
partial_document | Document edges cut off | Capture entire document |
glare_detected | Light reflection on document | Retake without flash |
wrong_document_type | Not the expected document | Upload correct type |
ocr_failed | Couldn't extract required data | Upload clearer image |
face_not_detected | No face found (ID documents) | Ensure photo is visible |
Screening Check Statuses
Status Diagram
ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎ
↓ PENDING ↓ↀↀ>↓ PROCESSING ↓ↀ↏ↀ>↓ CLEAR ↓
ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎ
↔ↀↀ↏ↀↀↀↀ←
v v
ⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎ
‚Üì HIT ‚Üì ‚Üì ERROR ‚Üì
ⅎⅎⅎⅎⅎⅎⅎ ⅎⅎⅎⅎⅎⅎⅎⅎⅎ
Status Definitions
| Status | Description | Next Actions |
|---|---|---|
pending | Check queued for processing | Wait |
processing | Check running against lists | Wait |
clear | No matches found | Continue verification |
hit | Potential matches found | Review hits |
error | Check failed (retry possible) | Retry or escalate |
Screening Hit Statuses
Resolution Status
| Status | Description | Who Sets |
|---|---|---|
pending | Hit awaiting review | System (default) |
confirmed_true | Hit confirmed as real match | Reviewer |
confirmed_false | Hit confirmed as false positive | Reviewer |
Step Statuses
Verification steps (document, selfie, screening) have their own statuses:
| Status | Description |
|---|---|
pending | Step not started |
in_progress | Step started but not complete |
complete | Step successfully completed |
failed | Step failed (may allow retry) |
skipped | Step skipped (workflow rules) |
Case Statuses
| Status | Description |
|---|---|
open | Case created, awaiting assignment |
in_progress | Case assigned and being investigated |
pending_info | Waiting for additional information |
resolved | Investigation complete |
escalated | Escalated to senior reviewer |
closed | Case closed |
Webhook Events by Status
| Event | Trigger |
|---|---|
applicant.created | Applicant created (status: pending) |
applicant.updated | Any applicant data change |
applicant.reviewed | Status changed to approved/rejected |
document.uploaded | Document uploaded (status: pending) |
document.verified | Document processing complete |
screening.completed | Screening check finished |
screening.hit_found | New screening hit detected |
case.created | New case opened |
case.resolved | Case resolved |
Handling Status Changes
Polling vs. Webhooks
Polling (Not Recommended):
# Don't do this in production
while True:
applicant = get_applicant(applicant_id)
if applicant["status"] in ["approved", "rejected"]:
break
time.sleep(5)
Webhooks (Recommended):
@app.route("/webhooks/trustgate", methods=["POST"])
def handle_webhook():
event = request.json
if event["event"] == "applicant.reviewed":
applicant_id = event["data"]["applicant_id"]
status = event["data"]["status"]
if status == "approved":
grant_account_access(applicant_id)
elif status == "rejected":
send_rejection_email(applicant_id)
return {"status": "received"}, 200
Error Handling
def handle_verification_error(applicant_id, error_type):
if error_type == "screening_error":
# Retry screening
retry_screening(applicant_id)
elif error_type == "document_rejected":
# Notify user to re-upload
notify_user(
applicant_id,
"Please upload a clearer image of your document"
)
elif error_type == "biometric_failed":
# Allow retry or escalate
increment_biometric_attempts(applicant_id)
if get_biometric_attempts(applicant_id) >= 3:
create_manual_review_case(applicant_id)
Next Steps
- Quick Start Guide - Build your first verification flow
- Webhooks - Set up real-time notifications
- API Reference - Full API documentation