KwadMarket Docs
Product Roadmap

Seller Verification

Photo-code verification, trust scores and scam prevention layers

Problem

On C2C marketplaces, scammers post deals with stolen photos. We need a way to prove the seller actually has the product.

Verification code system

When a deal reaches PENDING (submitted for review), generate a unique 5-character alphanumeric code (e.g. GK34L).
The seller writes the code on paper and photographs it next to the product.
The photo uploads as a special image (not a regular deal image).
Admin reviews the photo during deal moderation.
The deal gets a "Verified" badge if the code matches.

Data model

model DealVerification {
  id                Int      @id @default(autoincrement())
  dealId            Int      @unique
  deal              Deal     @relation(fields: [dealId], references: [id])
  code              String   // e.g. "GK34L"
  verificationImage String?  // S3 URL of the photo with code
  status            VerificationStatus @default(PENDING)
  reviewedAt        DateTime?
  reviewedBy        String?  // admin user ID
  rejectionReason   String?
  createdAt         DateTime @default(now())
}

enum VerificationStatus {
  PENDING      // code generated, waiting for photo
  SUBMITTED    // seller uploaded photo
  VERIFIED     // admin confirmed
  REJECTED     // photo doesn't match / suspicious
}

Code generation

  • 5 chars: uppercase letters + digits, excluding ambiguous chars (0/O, 1/I/L)
  • Alphabet: ABCDEFGHJKMNPQRSTUVWXYZ23456789 (29 chars) → ~20M combinations
  • Codes are unique per-deal, not globally (can be reused across deals)

Additional scam layers (V1)

Image metadata check — extract EXIF from uploads; flag photos taken >30 days ago, GPS mismatching the declared location, or the same image hash appearing in another deal (reverse image detection).

Seller trust score — based on completed deals, account age, verified deals, dispute ratio; displayed on deal page and seller profile.

model UserTrustScore {
  userId         String   @id
  user           User     @relation(fields: [userId], references: [id])
  completedDeals Int      @default(0)
  disputeCount   Int      @default(0)
  verifiedDeals  Int      @default(0)
  level          TrustLevel @default(NEW)
  updatedAt      DateTime @updatedAt
}

enum TrustLevel {
  NEW         // 0 deals
  VERIFIED    // 1+ verified deals, 0 disputes
  TRUSTED     // 5+ verified deals, <10% dispute rate
  TOP_SELLER  // 20+ verified deals, <5% dispute rate
}

Advanced scam detection (V2)

  • Perceptual image hashing (pHash) to detect stolen/reused product photos across deals
  • ML-based price anomaly detection (deals priced way below market value)
  • Account behavior analysis (multiple accounts from same IP, rapid deal creation)
  • Integration with community reports/flags

Tasks

  • DealVerification model + code generation utility; auto-generate on submission for review
  • Verification photo upload endpoint (separate from deal images)
  • Admin UI: verification photo + code side by side during moderation
  • "Verified" badge component on deal cards/pages
  • EXIF extraction on upload (date, GPS); image hash storage for duplicate detection
  • UserTrustScore model + auto-update on deal completion; trust level badge on profile

Decision: verification is optional but rewarded

Verified deals get a badge and rank higher in search. Unverified deals are still allowed. This reduces seller drop-off while incentivizing verification.

On this page