Verification Flow
A verification moves through a series of states as documents, selfies, and liveness data are submitted. Understanding this flow is key to building a correct integration.
State machine
┌──────────────────────┐
│ pending │
└──────────┬───────────┘
│ POST /complete
┌──────────▼───────────┐
│ processing │
└──────────┬───────────┘
│ Scoring + decision
┌───────────┬──┴──────────┬──────────────┐
│ │ │ │
┌──────▼───┐ ┌────▼────┐ ┌──────▼──────┐ ┌─────▼──┐
│ verified │ │rejected │ │manual_review│ │ failed │
└──────────┘ └─────────┘ └─────────────┘ └────────┘
Timeout (24h) from pending → expired
Valid states
| State | Description |
|---|---|
pending | Verification created, awaiting document/selfie uploads and completion |
processing | Verification submitted, scoring and decision in progress |
verified | All checks passed, verification approved |
rejected | Verification rejected (tampering, sanctions hit, low score) |
failed | Processing error occurred |
manual_review | Borderline score or PEP hit, queued for human review |
expired | Session expired before completion (24-hour timeout) |
Step-by-step
1. Create verification (pending)
Create a session with the subject's external ID and desired verification tier.
POST /api/v1/verifications
{
"externalId": "user-123",
"tier": "standard",
"callbackUrl": "https://your-server.com/webhooks/koraidv"
}
Response:
{
"id": "ver_abc123",
"status": "pending",
"tier": "standard",
"createdAt": "2025-01-15T10:30:00Z"
}
2. Upload document front
Upload the front of the identity document. The API runs document quality checks and begins authenticity analysis. The verification remains in pending state during uploads.
POST /api/v1/verifications/{id}/document
Optional: Upload the back of the document for two-sided IDs (driver's licenses, national IDs):
POST /api/v1/verifications/{id}/document/back
3. Upload selfie
Upload a selfie photo for face matching against the document photo.
POST /api/v1/verifications/{id}/selfie
The API extracts face embeddings and computes a similarity score.
4. Liveness detection
Liveness is optional but recommended. It confirms the person is physically present.
# Create a liveness session (returns challenges)
POST /api/v1/verifications/{id}/liveness/session
# Submit each challenge response
POST /api/v1/verifications/{id}/liveness/challenge
# Check liveness result
GET /api/v1/verifications/{id}/liveness
The mobile SDKs handle liveness automatically — they guide the user through challenges and submit frames. You only need these endpoints if building a custom liveness UI.
5. Complete verification (pending → processing → final state)
Trigger final scoring, compliance screening, and the automated decision.
POST /api/v1/verifications/{id}/complete
This runs:
- 5-layer document authenticity (template, font, photo integrity, compression, edge)
- Face match scoring (FaceNet embedding comparison)
- Anti-spoof analysis (if liveness data present)
- Compliance screening (sanctions, PEP, adverse media via CEngine)
- Final score calculation and decision
6. Decision
The verification receives one of three decision outcomes:
| Decision | Final State | Meaning | Typical action |
|---|---|---|---|
auto_approve | verified | All checks passed, score above threshold | Onboard the user |
auto_reject | rejected | Critical failure (tampering, sanctions hit, spoof) | Block the user |
manual_review | manual_review | Borderline score or PEP hit | Queue for human review |
Verification tiers
Tiers control which checks run:
| Tier | Document Auth | Face Match | Liveness | Compliance |
|---|---|---|---|---|
basic | Yes | No | No | No |
standard | Yes | Yes | Optional | Yes |
professional | Yes | Yes | Required | Yes |
enterprise | Yes | Yes | Required | Yes (enhanced) |
Expiration
Verifications expire after 24 hours if not completed. Expired verifications cannot be resumed — create a new one.