Skip to content

YeboVerify Database Models

YeboVerify uses Prisma ORM with PostgreSQL.

Business

Registered businesses using YeboVerify.

prisma
model Business {
  id            String   @id @default(cuid())
  name          String
  email         String   @unique
  apiKey        String   @unique
  plan          String   @default("starter")
  webhookUrl    String?
  webhookSecret String?
  isActive      Boolean  @default(true)
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
  
  verifications Verification[]
}

Verification

Core verification record.

prisma
model Verification {
  id             String             @id @default(cuid())
  verificationId String             @unique    // Public ID (vrf_xxx)
  
  // Business reference
  businessId     String
  business       Business           @relation(fields: [businessId], references: [id])
  externalRef    String?                       // Business's reference
  
  // Status
  status         VerificationStatus @default(PENDING)
  
  // Images (R2 keys - private)
  idFrontImage   String
  idBackImage    String?
  selfieImage    String
  
  // Results
  faceScore      Float?                        // 0-100
  faceDecision   String?                       // 'approved', 'rejected', 'needs_review'
  ocrConfidence  Float?                        // 0-100
  extractedData  Json?                         // Parsed document fields
  
  // Decision
  decision       Decision?
  decisionReason String?
  confidence     String?                       // 'high', 'medium', 'low'
  
  // Processing
  processingMs   Int?
  
  // Webhook
  webhookSent    Boolean   @default(false)
  webhookSentAt  DateTime?
  webhookError   String?
  
  // Timestamps
  createdAt      DateTime  @default(now())
  completedAt    DateTime?
}

enum VerificationStatus {
  PENDING
  PROCESSING
  COMPLETED
  FAILED
  NEEDS_REVIEW
}

enum Decision {
  APPROVED
  REJECTED
  NEEDS_REVIEW
}

Extracted Data Schema

The extractedData JSON field contains:

typescript
interface ExtractedData {
  surname?: string;        // Last name
  names?: string;          // First + middle names
  dateOfBirth?: string;    // YYYY-MM-DD
  idNumber?: string;       // Document number
  documentType?: string;   // "National ID", "Passport", etc.
  nationality?: string;    // Country
  expiryDate?: string;     // Document expiry
  gender?: string;         // M/F
  address?: string;        // If present on document
}

Indexes

prisma
@@index([businessId])
@@index([verificationId])
@@index([status])
@@index([createdAt])

Example Verification Record

json
{
  "id": "clx123abc",
  "verificationId": "vrf_abc123xyz",
  "businessId": "clx456def",
  "externalRef": "user_789",
  "status": "COMPLETED",
  "idFrontImage": "verifications/vrf_abc123xyz/id-front-1705315200000",
  "idBackImage": null,
  "selfieImage": "verifications/vrf_abc123xyz/selfie-1705315200000",
  "faceScore": 92.5,
  "faceDecision": "approved",
  "ocrConfidence": 85.0,
  "extractedData": {
    "surname": "Doe",
    "names": "John James",
    "dateOfBirth": "1990-05-15",
    "idNumber": "123456789",
    "documentType": "National ID"
  },
  "decision": "APPROVED",
  "decisionReason": "High face match and OCR confidence",
  "confidence": "high",
  "processingMs": 3250,
  "webhookSent": true,
  "webhookSentAt": "2024-01-15T10:00:04Z",
  "webhookError": null,
  "createdAt": "2024-01-15T10:00:00Z",
  "completedAt": "2024-01-15T10:00:03Z"
}

Relationships

Business 1──────* Verification

Data Retention

Images stored in R2:

  • Private bucket - Not publicly accessible
  • Encrypted at rest
  • Retention policy - Configurable per business

One chat. Everything done.