Skip to content

Zaptam - Product Requirements Document

Version: 1.0
Last Updated: March 2026
Status: Built & Documented


Table of Contents

  1. Executive Summary
  2. Vision & Mission
  3. Problem Statement
  4. Solution Overview
  5. Target Audience
  6. Core Features
  7. User Journeys
  8. Data Models
  9. API Reference
  10. Service Architecture
  11. Matching Algorithm
  12. Authentication System
  13. Billing & Premium Features
  14. Content Moderation & Trust System
  15. Technical Stack
  16. Gaps & Missing Features

1. Executive Summary

Zaptam is a private, verified dating and companionship network targeting the African market with a focus on exclusivity, discretion, and trust. Unlike traditional dating apps, Zaptam implements a rigorous verification system where:

  • Men must verify their financial capacity ("worth verification")
  • Women must verify their identity ("value verification")

The platform operates on a gender-asymmetric business model:

  • Men pay for membership ($49-$499/month)
  • Women join free after passing verification and acceptance review

The system consists of four interconnected applications:

  • zaptam-api: Backend REST API + WebSocket server
  • zaptam-app: User-facing mobile/web app (React)
  • zaptam-admin: Administrative dashboard (React)
  • zaptam-landing: Marketing website (React)

2. Vision & Mission

Vision

"Not Everyone Deserves Access" — Create the most trusted network for adults seeking genuine connections through rigorous verification and exclusive membership.

Mission

  • Build a high-trust dating network where worth and value are verified, not claimed
  • Protect user privacy with industry-leading security measures
  • Maintain quality through selective approval and ongoing behavioral monitoring
  • Create a value balance: men bring financial capacity, women bring authentic presence

Core Principles

  1. Verification First: Every member undergoes rigorous screening
  2. Privacy Protected: Screenshot protection, alias mode, encrypted messaging
  3. Quality Over Quantity: 8% acceptance rate (claimed target)
  4. Discretion First: No public profiles, no social sharing
  5. Zero Tolerance: Immediate action on misconduct

3. Problem Statement

Industry Problems

  1. Fake Profiles: Traditional dating apps are plagued with fake accounts and catfishing
  2. Low Commitment: Free apps attract users who aren't invested
  3. Privacy Concerns: Users fear exposure and lack control over their data
  4. Misaligned Incentives: Apps optimize for time spent swiping, not actual connections
  5. Safety Issues: Inadequate verification leads to harassment, scams, and blackmail

African Market Specific

  • Cultural need for discretion in dating
  • Growing affluent population seeking premium services
  • Lack of high-quality, verified dating platforms in the region
  • Trust deficit in online interactions

4. Solution Overview

Zaptam addresses these problems through:

ProblemSolution
Fake profilesMulti-tier verification system (ID, Worth, Value)
Low commitmentPaid membership for men ($49-499/month)
Privacy concernsAlias mode, photo blur, screenshot detection, panic delete
Misaligned incentivesMatch-based messaging (must both express interest)
Safety issuesTrust scoring, behavioral monitoring, blackmail hotline

Key Differentiators

  • Worth Verification (Men): Financial capacity demonstration
  • Value Verification (Women): Identity verification + selective acceptance
  • Trust Score: Dynamic 0-100 score based on behavior
  • Panic Delete: Instant, permanent data wipe
  • Screenshot Detection: Notify victims + trust penalty for offender

5. Target Audience

Male Users

  • Demographics: 25-55, professional/business owners
  • Income: Upper-middle to high income
  • Needs: Quality connections, discretion, verified partners
  • Pain Points: Fake profiles, time-wasters, privacy exposure

Female Users

  • Demographics: 21-45, various backgrounds
  • Needs: Safe environment, verified partners, earning potential
  • Pain Points: Harassment, fake profiles, unwanted exposure
  • Incentive: Free access + earnings from engagement

Admin Users

  • Curators: Review verifications, handle basic reports
  • Admins: User management, payouts, advanced moderation
  • Super Admins: Full system access, analytics, configuration

6. Core Features

6.1 User Features

Authentication & Onboarding

  • Phone number registration with OTP verification
  • Gender-specific application process
  • Multi-step profile completion
  • Password-protected accounts
  • Refresh token rotation

Profile Management

  • Alias mode (hide real name)
  • Bio and personal information
  • Photo gallery with blur control
  • Verification badges
  • Trust score display

Discovery & Matching

  • Browse opposite gender profiles (default)
  • Filter by verification level
  • Express interest (one-way)
  • Mutual match detection
  • Priority ordering (verified + high trust first)

Messaging

  • Real-time WebSocket messaging
  • Conversation list with unread counts
  • Typing indicators
  • Read receipts
  • Disappearing messages (configurable)
  • Media sharing

Privacy Controls

  • Alias Mode: Use generated alias instead of real name
  • Photo Blur: Set blur level 0-100% on photos
  • Region Masking: Hide exact location
  • Online Status: Toggle visibility
  • Disappearing Messages: Auto-delete after set hours
  • Panic Delete: Instant account wipe

Wallet & Transactions

  • View balance (USD)
  • Purchase credits (men)
  • Request withdrawals (women)
  • Transaction history
  • Membership tier selection

6.2 Admin Features

Dashboard

  • Total users (by gender, status)
  • Pending verifications count
  • Pending reports count
  • Total matches
  • User growth trends
  • Revenue metrics

User Management

  • List all users with filters/search
  • View user details
  • Update user status (suspend/ban)
  • Adjust trust scores
  • Change verification levels

Verification Queue

  • List pending verifications
  • Review documents
  • Approve/reject with notes
  • Auto-update user verification level

Report Handling

  • List reports by type/status
  • View report details
  • Resolve or dismiss
  • Apply trust penalties
  • Ban offenders

Transaction Management

  • View all transactions
  • Process withdrawal requests
  • Approve/reject payouts
  • Revenue analytics

7. User Journeys

7.1 Male User Journey

1. DISCOVER → Landing page exposure

2. APPLY → Submit application (phone, gender, email, occupation, net worth)

3. VERIFY PHONE → Receive OTP via WhatsApp/SMS, enter code

4. COMPLETE PROFILE → Set password, bio, date of birth

5. PENDING APPROVAL → Wait for admin to approve worth verification

6. ACTIVATED → Account becomes ACTIVE

7. SUBSCRIBE → Choose membership tier ($49/$149/$499)

8. PURCHASE CREDITS → Buy credits for messaging/unlocks

9. DISCOVER → Browse verified female profiles

10. EXPRESS INTEREST → Send interest to profiles

11. MATCH → When interest is mutual

12. MESSAGE → Start conversation with match

13. MEET → Arrange real-world meeting

7.2 Female User Journey

1. DISCOVER → Landing page exposure

2. APPLY → Submit application (phone, gender, email, intro, photos)

3. VERIFY PHONE → Receive OTP, enter code

4. COMPLETE PROFILE → Set password, bio, date of birth

5. IDENTITY VERIFICATION → Submit ID documents

6. ACCEPTANCE REVIEW → Admin reviews (may reject even if verified)

7. ACTIVATED → Account becomes ACTIVE (free membership)

8. DISCOVER → Browse verified male profiles

9. RECEIVE INTERESTS → Get notified of interests

10. ACCEPT/DECLINE → Respond to interests

11. MATCH → Interest accepted = match created

12. MESSAGE → Chat with matches

13. EARN → Receive earnings from engagement (to wallet)

14. WITHDRAW → Request payout (min $10)

7.3 Admin Journey

1. LOGIN → Authenticate with admin credentials

2. DASHBOARD → View system overview

3. VERIFICATIONS → Review pending verifications
   ├── APPROVE → User level upgraded
   └── REJECT → User notified, can resubmit

4. REPORTS → Handle user reports
   ├── INVESTIGATE → Escalate blackmail
   ├── RESOLVE → Apply penalties, ban if needed
   └── DISMISS → Close without action

5. USERS → Manage user accounts
   ├── SUSPEND → Temporary restriction
   ├── BAN → Permanent block
   └── RECALCULATE TRUST → Update trust score

6. PAYOUTS → Process withdrawal requests
   ├── APPROVE → Release funds
   └── REJECT → Notify user

7. ANALYTICS → Review growth and revenue metrics

8. Data Models

8.1 User Model

typescript
model User {
  id                String            @id @default(uuid()) @db.Uuid
  phoneNumber       String            @unique
  email             String?           @unique
  password          String?           // Hashed, nullable during application
  role              UserRole          @default(USER)
  gender            Gender?           // MALE | FEMALE
  status            UserStatus        @default(PENDING)

  // Profile
  alias             String?           @unique    // System-generated or custom
  name              String?                      // Real name (hidden in alias mode)
  bio               String?                      // User description
  occupation        String?                      // For male users
  intro             String?                      // For female users
  netWorth          String?                      // For male users
  dateOfBirth       DateTime?

  // Trust & Verification
  trustScore        Int               @default(50)  // 0-100
  verificationLevel VerificationLevel @default(NONE)

  // Timestamps
  lastActiveAt      DateTime?
  createdAt         DateTime          @default(now())
  updatedAt         DateTime          @updatedAt
  deletedAt         DateTime?         // Soft delete

  // Relations
  settings          UserSettings?
  photos            Photo[]
  sentMessages      Message[]            @relation("sender")
  receivedMessages  Message[]            @relation("recipient")
  sentInterests     Interest[]           @relation("sender")
  receivedInterests Interest[]           @relation("recipient")
  verifications     Verification[]
  walletTransactions WalletTransaction[]
  reports           Report[]             @relation("reporter")
  reportedBy        Report[]             @relation("reported")
  conversations1    Conversation[]       @relation("participant1")
  conversations2    Conversation[]       @relation("participant2")
  refreshTokens     RefreshToken[]
  otpCodes          OtpCode[]
}

8.2 UserSettings Model

typescript
model UserSettings {
  id               String  @id @default(uuid()) @db.Uuid
  userId           String  @unique @db.Uuid
  
  aliasMode        Boolean @default(true)      // Hide real name
  showOnlineStatus Boolean @default(false)     // Show when online
  regionMasking    Boolean @default(true)      // Hide exact location
  photoBlurLevel   Int     @default(100)       // 0-100, default fully blurred
  disappearingMsgs Int?                        // Hours until auto-delete
}

8.3 Photo Model

typescript
model Photo {
  id        String   @id @default(uuid()) @db.Uuid
  userId    String   @db.Uuid
  url       String                           // R2/S3 URL
  blurLevel Int      @default(100)           // 0-100
  isPrimary Boolean  @default(false)         // Main profile photo
  order     Int      @default(0)             // Display order
  createdAt DateTime @default(now())
}

8.4 Interest Model

typescript
model Interest {
  id          String         @id @default(uuid()) @db.Uuid
  senderId    String         @db.Uuid
  recipientId String         @db.Uuid
  status      InterestStatus @default(PENDING)  // PENDING | ACCEPTED | DECLINED
  createdAt   DateTime       @default(now())

  @@unique([senderId, recipientId])  // Prevent duplicate interests
}

8.5 Conversation Model

typescript
model Conversation {
  id             String    @id @default(uuid()) @db.Uuid
  participant1Id String    @db.Uuid
  participant2Id String    @db.Uuid
  messages       Message[]
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt

  @@unique([participant1Id, participant2Id])
}

8.6 Message Model

typescript
model Message {
  id             String       @id @default(uuid()) @db.Uuid
  conversationId String       @db.Uuid
  senderId       String       @db.Uuid
  recipientId    String       @db.Uuid
  content        String?                          // Text content
  mediaUrl       String?                          // Media attachment URL
  isRead         Boolean      @default(false)
  expiresAt      DateTime?                        // Disappearing message
  deletedAt      DateTime?                        // Soft delete
  createdAt      DateTime     @default(now())
}

8.7 Verification Model

typescript
model Verification {
  id         String             @id @default(uuid()) @db.Uuid
  userId     String             @db.Uuid
  type       VerificationType   // IDENTITY | WORTH | VALUE
  status     VerificationStatus @default(PENDING)
  documents  Json?              // Array of document URLs
  notes      String?            // Admin notes
  reviewedBy String?            @db.Uuid
  reviewedAt DateTime?
  createdAt  DateTime           @default(now())
}

8.8 WalletTransaction Model

typescript
model WalletTransaction {
  id        String            @id @default(uuid()) @db.Uuid
  userId    String            @db.Uuid
  type      TransactionType   // MEMBERSHIP | CREDIT_PURCHASE | EARNING | WITHDRAWAL | BOOST
  amount    Decimal           @db.Decimal(10, 2)
  currency  String            @default("USD")
  status    TransactionStatus @default(PENDING)  // PENDING | COMPLETED | FAILED | REFUNDED
  reference String?           // Payment gateway reference
  createdAt DateTime          @default(now())
}

8.9 Report Model

typescript
model Report {
  id          String       @id @default(uuid()) @db.Uuid
  reporterId  String       @db.Uuid           // Who filed the report
  reportedId  String       @db.Uuid           // Who is being reported
  type        ReportType   // BLACKMAIL | HARASSMENT | FAKE_PROFILE | INAPPROPRIATE_CONTENT | OTHER
  description String                          // Detailed description
  evidence    Json?                           // Screenshots, links, etc.
  status      ReportStatus @default(PENDING)  // PENDING | INVESTIGATING | RESOLVED | DISMISSED
  resolution  String?                         // Admin's resolution notes
  resolvedBy  String?      @db.Uuid
  resolvedAt  DateTime?
  createdAt   DateTime     @default(now())
}

8.10 MembershipTier Model

typescript
model MembershipTier {
  id        String   @id @default(uuid()) @db.Uuid
  name      String                           // Standard, Premium, Elite
  price     Decimal  @db.Decimal(10, 2)      // Monthly price in USD
  currency  String   @default("USD")
  duration  Int                              // Days
  features  Json                             // Array of feature strings
  isActive  Boolean  @default(true)
  createdAt DateTime @default(now())
}

8.11 RefreshToken Model

typescript
model RefreshToken {
  id        String   @id @default(uuid()) @db.Uuid
  userId    String   @db.Uuid
  token     String   @unique
  expiresAt DateTime
  createdAt DateTime @default(now())
}

8.12 OtpCode Model

typescript
model OtpCode {
  id        String     @id @default(uuid()) @db.Uuid
  userId    String?    @db.Uuid
  phone     String
  code      String                           // 6-digit code
  purpose   OtpPurpose // REGISTRATION | LOGIN | PASSWORD_RESET
  expiresAt DateTime
  usedAt    DateTime?
  createdAt DateTime   @default(now())
}

8.13 Enums

typescript
enum UserRole {
  USER
  CURATOR
  ADMIN
  SUPER_ADMIN
}

enum Gender {
  MALE
  FEMALE
}

enum UserStatus {
  PENDING      // Application submitted
  ACTIVE       // Approved and verified
  SUSPENDED    // Temporarily restricted
  BANNED       // Permanently blocked
  DELETED      // Soft deleted
}

enum VerificationLevel {
  NONE         // No verification
  IDENTITY     // ID verified
  FULL         // ID + Worth/Value verified
}

enum VerificationType {
  IDENTITY     // Government ID
  WORTH        // Financial capacity (men)
  VALUE        // Additional verification (women)
}

enum VerificationStatus {
  PENDING
  APPROVED
  REJECTED
}

enum InterestStatus {
  PENDING
  ACCEPTED
  DECLINED
}

enum TransactionType {
  MEMBERSHIP
  CREDIT_PURCHASE
  EARNING
  WITHDRAWAL
  BOOST
}

enum TransactionStatus {
  PENDING
  COMPLETED
  FAILED
  REFUNDED
}

enum ReportType {
  BLACKMAIL
  HARASSMENT
  FAKE_PROFILE
  INAPPROPRIATE_CONTENT
  OTHER
}

enum ReportStatus {
  PENDING
  INVESTIGATING
  RESOLVED
  DISMISSED
}

enum OtpPurpose {
  REGISTRATION
  LOGIN
  PASSWORD_RESET
}

9. API Reference

9.1 Base URL & Headers

Production: https://api.zaptam.com
Local: http://localhost:3000

Headers:
  Content-Type: application/json
  Authorization: Bearer <access_token>  (for protected routes)

9.2 Authentication Endpoints

MethodEndpointDescriptionAuth
POST/api/auth/applySubmit applicationNo
POST/api/auth/verify-phoneSend OTP to phoneNo
POST/api/auth/confirm-phoneVerify OTP codeNo
POST/api/auth/complete-profileComplete registrationNo
POST/api/auth/loginLogin with credentialsNo
POST/api/auth/refreshRefresh access tokenNo
POST/api/auth/logoutInvalidate tokensYes
POST/api/auth/forgot-passwordRequest password resetNo
POST/api/auth/reset-passwordReset password with codeNo

9.3 User Endpoints

MethodEndpointDescriptionAuth
GET/api/users/meGet current userYes
PATCH/api/users/meUpdate profileYes
GET/api/users/me/settingsGet settingsYes
PATCH/api/users/me/settingsUpdate settingsYes
POST/api/users/me/photosUpload photoYes
DELETE/api/users/me/photos/:idDelete photoYes
DELETE/api/users/meDelete accountYes
POST/api/users/me/panic-deletePanic delete (hard)Yes

9.4 Discovery & Profile Endpoints

MethodEndpointDescriptionAuth
GET/api/discoverBrowse profilesYes
GET/api/profiles/:idView profile detailYes
POST/api/profiles/:id/interestExpress interestYes

9.5 Match Endpoints

MethodEndpointDescriptionAuth
GET/api/matchesGet all matchesYes
DELETE/api/matches/:idRemove/decline matchYes

9.6 Message Endpoints

MethodEndpointDescriptionAuth
GET/api/messages/conversationsList conversationsYes
GET/api/messages/conversations/:idGet messagesYes
POST/api/messages/conversations/:idSend messageYes
DELETE/api/messages/conversations/:idDelete conversationYes
POST/api/messages/messages/:id/reportReport a messageYes

9.7 Wallet Endpoints

MethodEndpointDescriptionAuth
GET/api/walletGet balanceYes
GET/api/wallet/transactionsTransaction historyYes
POST/api/wallet/purchasePurchase creditsYes
POST/api/wallet/withdrawRequest withdrawalYes
GET/api/wallet/membership-tiersGet membership optionsYes

9.8 Verification Endpoints

MethodEndpointDescriptionAuth
GET/api/verification/statusGet verification statusYes
POST/api/verification/identitySubmit ID verificationYes
POST/api/verification/worthSubmit worth (men)Yes
POST/api/verification/valueSubmit value (women)Yes

9.9 Report Endpoints

MethodEndpointDescriptionAuth
POST/api/reportsSubmit reportYes
POST/api/reports/blackmailEmergency blackmail reportYes
GET/api/reports/my-reportsView submitted reportsYes

9.10 Admin Endpoints

MethodEndpointDescriptionRequired Role
GET/api/admin/dashboardDashboard statsCURATOR+
GET/api/admin/usersList usersCURATOR+
GET/api/admin/users/:idUser detailCURATOR+
PATCH/api/admin/users/:idUpdate userADMIN+
POST/api/admin/users/:id/suspendSuspend userADMIN+
POST/api/admin/users/:id/banBan userADMIN+
POST/api/admin/users/:id/recalculate-trustRecalc trustCURATOR+
GET/api/admin/verificationsVerification queueCURATOR+
PATCH/api/admin/verifications/:idReview verificationCURATOR+
GET/api/admin/reportsList reportsCURATOR+
GET/api/admin/reports/:idReport detailCURATOR+
PATCH/api/admin/reports/:idHandle reportCURATOR+
GET/api/admin/transactionsAll transactionsCURATOR+
GET/api/admin/payoutsPayout requestsCURATOR+
PATCH/api/admin/payouts/:idProcess payoutADMIN+
GET/api/admin/analyticsAnalytics dataCURATOR+

9.11 WebSocket Events

Connection: ws://api.zaptam.com with auth.token in handshake

Client → Server:

EventPayloadDescription
join:conversationconversationId: stringJoin conversation room
leave:conversationconversationId: stringLeave conversation room
message:send{ conversationId, content, mediaUrl?, expiresIn? }Send message
message:readconversationId: stringMark messages as read
typing:startconversationId: stringStart typing indicator
typing:stopconversationId: stringStop typing indicator
presence:checktargetUserId: stringCheck if user is online
presence:bulk-checkuserIds: string[]Check multiple users
screenshot:detected{ conversationId? }Report screenshot taken

Server → Client:

EventPayloadDescription
message:new{ conversationId, message }New message received
message:read{ conversationId, readBy }Messages were read
typing:start{ conversationId, userId }User started typing
typing:stop{ conversationId, userId }User stopped typing
user:online{ userId }User came online
user:offline{ userId }User went offline
notification:message{ conversationId, senderId, preview }New message notification
screenshot:alert{ conversationId, userId }Screenshot detected

10. Service Architecture

10.1 System Overview

┌─────────────────────────────────────────────────────────────────┐
│                         CLIENTS                                  │
├─────────────────┬─────────────────┬─────────────────────────────┤
│   zaptam-app    │  zaptam-admin   │      zaptam-landing         │
│   (React SPA)   │   (React SPA)   │        (React SPA)          │
│   Port: 5173    │   Port: 5174    │        Port: 5175           │
└────────┬────────┴────────┬────────┴─────────────────────────────┘
         │                 │
         ├─────────────────┼──────────────────────────────────────┐
         │                 │                                      │
         ▼                 ▼                                      │
┌─────────────────────────────────────────────────────────────────┤
│                      zaptam-api                                  │
│                    (Express + Socket.IO)                         │
│                       Port: 3000                                 │
├─────────────────────────────────────────────────────────────────┤
│  Routes          │  Services       │  Sockets                    │
│  ├─ auth         │  ├─ auth        │  ├─ message.socket          │
│  ├─ users        │  ├─ user        │  └─ presence.socket         │
│  ├─ profiles     │  ├─ match       │                             │
│  ├─ matches      │  ├─ message     │  Middleware                 │
│  ├─ messages     │  ├─ wallet      │  ├─ auth.middleware         │
│  ├─ wallet       │  ├─ verification│  ├─ role.middleware         │
│  ├─ verification │  ├─ report      │  ├─ validation.middleware   │
│  ├─ reports      │  ├─ trust       │  ├─ rateLimit.middleware    │
│  └─ admin/*      │  └─ notification│  └─ error.middleware        │
└────────┬────────────────┬────────────────────────────────────────┘
         │                │
         ▼                ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────────┐
│   PostgreSQL    │ │ Cloudflare R2    │ │ Notification Service    │
│   (via Prisma)  │ │ (Photo Storage)  │ │ (External API)          │
└─────────────────┘ └──────────────────┘ └─────────────────────────┘

10.2 Service Modules

AuthService (auth.service.ts)

  • applyForAccount() - Handle new applications
  • sendPhoneOtp() - Send verification codes
  • verifyOtp() - Validate OTP codes
  • completeRegistration() - Finalize account setup
  • login() - Authenticate users
  • refreshAccessToken() - Token rotation
  • logout() - Invalidate tokens
  • resetPassword() - Password recovery

UserService (user.service.ts)

  • getUserById() - Fetch user profile
  • getUserSettings() - Fetch settings
  • updateProfile() - Update user info
  • updateSettings() - Update privacy settings
  • changePassword() - Password change
  • deleteAccount() - Soft delete
  • panicDelete() - Hard delete (all data)
  • updateLastActive() - Track activity

MatchService (match.service.ts)

  • discoverProfiles() - Browse with filters
  • getProfileById() - View detailed profile
  • expressInterest() - Send interest
  • getMatches() - List mutual matches
  • declineMatch() - Remove match

MessageService (message.service.ts)

  • getConversations() - List conversations
  • getMessages() - Fetch messages
  • sendMessage() - Send new message
  • deleteConversation() - Remove conversation
  • getOrCreateConversation() - Ensure conversation exists

WalletService (wallet.service.ts)

  • getWalletBalance() - Calculate balance
  • getTransactionHistory() - List transactions
  • purchaseCredits() - Buy credits (men)
  • purchaseMembership() - Subscribe to tier
  • requestWithdrawal() - Request payout (women)
  • processWithdrawal() - Admin payout approval
  • getMembershipTiers() - Get pricing

VerificationService (verification.service.ts)

  • getVerificationStatus() - Check current level
  • submitVerification() - Submit documents
  • reviewVerification() - Admin review
  • getPendingVerifications() - Admin queue

ReportService (report.service.ts)

  • createReport() - Submit report
  • createBlackmailReport() - High-priority report
  • getReports() - Admin list
  • getReportById() - Report detail
  • getUserReports() - User's reports

TrustService (trust.service.ts)

  • calculateTrustScore() - Compute score
  • updateTrustScore() - Refresh score
  • applyTrustPenalty() - Deduct points
  • reportScreenshotDetected() - Screenshot penalty

NotificationService (notification.service.ts)

  • sendOtpNotification() - Send OTP via WhatsApp/SMS

10.3 Middleware Pipeline

Request → RateLimit → Auth → Role → Validation → Controller → Response
              ↓         ↓       ↓        ↓
           429 err   401 err  403 err  400 err

11. Matching Algorithm

11.1 Discovery Ordering

Profiles are ranked by:

  1. Verification Level (descending): FULL > IDENTITY > NONE
  2. Trust Score (descending): Higher scores first
  3. Last Active (descending): Recently active first

11.2 Interest & Match Flow

User A ──[Express Interest]──→ User B

         ├── If B has NOT expressed interest in A:
         │   └── Create Interest (A→B, status: PENDING)

         └── If B has already expressed interest in A:
             └── MUTUAL MATCH!
                 ├── Update B→A Interest to ACCEPTED
                 ├── Create A→B Interest as ACCEPTED
                 └── Create Conversation for A & B

11.3 Photo Blur Logic

For non-matched users:

typescript
blurLevel = Math.max(photo.blurLevel, 80) // At least 80% blur

For matched users:

typescript
blurLevel = photo.blurLevel // User's preferred blur level

12. Authentication System

12.1 Token Architecture

Token TypeExpiryStorageUse
Access Token15 minutesMemoryAPI requests
Refresh Token7 daysDatabase + ClientGet new access token
OTP Code10 minutesDatabasePhone verification

12.2 JWT Payload

typescript
{
  userId: string,
  role: UserRole,
  iat: number,
  exp: number
}

12.3 Token Flow

1. User logs in
2. Server generates access + refresh tokens
3. Access token sent in Authorization header
4. On 401, client sends refresh token
5. Server validates refresh token, issues new pair
6. Old refresh token invalidated (rotation)

12.4 OTP Flow

  1. Request OTP → sendPhoneOtp()
  2. External notification service sends code via WhatsApp/SMS
  3. User enters code
  4. verifyOtp() validates and marks code as used
  5. OTP expires after 10 minutes or single use

13. Billing & Premium Features

13.1 Membership Tiers (Men)

TierPriceFeatures
Standard$49/monthWorth verification, browse profiles, unlimited interest, messaging, basic privacy
Premium$149/month+ Worth badge, priority discovery, see who viewed, advanced privacy, read receipts
Elite$499/month+ Top placement, personal curator, exclusive events, monthly boost, 24/7 concierge

13.2 Women's Access

  • Price: Free
  • Requirement: Identity verification + acceptance review
  • Benefits: Full platform access, earnings from engagement, priority support

13.3 Transaction Types

TypeDirectionUser Type
MEMBERSHIPOutMen
CREDIT_PURCHASEIn (wallet credit)Men
EARNINGInWomen
WITHDRAWALOutWomen
BOOSTOutAll

13.4 Withdrawal Process

  1. Women request withdrawal (min $10)
  2. Transaction created with status PENDING
  3. Admin reviews in payout queue
  4. Admin approves → status COMPLETED, funds released
  5. Admin rejects → status FAILED, balance restored

14. Content Moderation & Trust System

14.1 Trust Score Algorithm

Base Score: 50 (starting value) Range: 0-100

Positive Factors:

FactorPointsMax
Verification Level (IDENTITY)+1010
Verification Level (FULL)+2020
Account Age+1/month10
Matches (Interactions)+1 per 2 matches10

Negative Factors:

FactorPoints
Valid Report Against User-5 each
Screenshot Detected-10 each

14.2 Report Types & Handling

TypePriorityAuto-Action
BLACKMAILCRITICALImmediate -20 trust, auto-investigate
HARASSMENTHIGHReview within 24h
FAKE_PROFILEMEDIUMReview within 48h
INAPPROPRIATE_CONTENTMEDIUMReview within 48h
OTHERLOWReview within 72h

14.3 Report Status Flow

PENDING → INVESTIGATING → RESOLVED
                       → DISMISSED

14.4 Screenshot Detection

  1. Client detects screenshot attempt
  2. Sends screenshot:detected socket event
  3. Server applies -10 trust penalty
  4. Server sends screenshot:alert to conversation partner
  5. Logged for review

14.5 Panic Delete

Permanently removes ALL user data:

  • Messages (sent and received)
  • Conversations
  • Interests (sent and received)
  • Photos
  • Verifications
  • Wallet transactions
  • Reports (filed and against)
  • Tokens
  • Settings
  • User record

15. Technical Stack

15.1 Backend (zaptam-api)

CategoryTechnology
RuntimeNode.js
FrameworkExpress.js 4.18
LanguageTypeScript 5.3
ORMPrisma 5.9
DatabasePostgreSQL
Real-timeSocket.IO 4.7
AuthJWT (jsonwebtoken 9.0)
ValidationJoi 17.12
File StorageCloudflare R2 (S3-compatible)
Password Hashingbcryptjs
Rate Limitingexpress-rate-limit
SecurityHelmet

15.2 Frontend Apps (zaptam-app, zaptam-admin)

CategoryTechnology
FrameworkReact 18
LanguageTypeScript 5.3
Build ToolVite 5.0
RouterReact Router 6.22
State ManagementZustand 4.5
Data FetchingTanStack Query 5.17
HTTP ClientAxios 1.6
Real-timeSocket.IO Client 4.7
UI ComponentsRadix UI
StylingTailwind CSS 3.4
AnimationFramer Motion 11
FormsReact Hook Form 7.50
Charts (Admin)Recharts 2.15

15.3 Landing Page (zaptam-landing)

CategoryTechnology
FrameworkReact 18
LanguageTypeScript 5.3
Build ToolVite 5.0
RouterReact Router 6.22
StylingTailwind CSS 3.4
AnimationFramer Motion 11

15.4 External Services

ServicePurpose
Cloudflare R2Photo storage
Notification Service (Eneza)WhatsApp/SMS OTP delivery
PostgreSQLPrimary database

16. Gaps & Missing Features

16.1 Not Yet Implemented

FeaturePriorityDescription
Payment Gateway IntegrationHIGHStripe/PayPal for actual payments (currently mock)
Push NotificationsHIGHFCM/APNs for mobile notifications
Email NotificationsMEDIUMTransactional emails (welcome, matches, etc.)
Photo ModerationHIGHAI-based nudity/inappropriate content detection
ID Verification IntegrationHIGHJumio/Onfido for automated ID verification
Worth VerificationHIGHPlaid/bank verification for financial capacity
Video CallsMEDIUMIn-app video calling for matches
Voice MessagesLOWAudio message support
Profile BoostMEDIUMPaid boost functionality
Exclusive EventsLOWElite tier event management
Personal CuratorLOWHuman matching assistance for Elite
Crypto PaymentsLOWBitcoin/crypto payment option
2FAMEDIUMTwo-factor authentication option
App Store DeploymentHIGHiOS/Android native apps (currently web only)

16.2 Technical Debt

IssueImpactSuggested Fix
No automated testsHIGHAdd Jest/Vitest test suites
No CI/CD pipelineMEDIUMSetup GitHub Actions
No logging infrastructureMEDIUMAdd structured logging (Pino/Winston)
No monitoringMEDIUMAdd APM (DataDog/NewRelic)
Hardcoded notification URLLOWMove to environment config
No database migrationsMEDIUMUse Prisma migrate instead of db push
No API versioningLOWAdd /api/v1/ prefix
No request tracingLOWAdd correlation IDs
Socket.IO not scalableMEDIUMAdd Redis adapter for multi-instance

16.3 Security Improvements Needed

IssuePriorityRecommendation
Rate limit bypassHIGHAdd Redis-backed rate limiting
No brute-force protectionHIGHAdd account lockout after failed attempts
JWT in memory onlyMEDIUMConsider HttpOnly cookies
No audit loggingMEDIUMLog all admin actions
Screenshot detection is client-sideLOWInform users this is deterrent only
Panic delete is irreversibleINFOAdd confirmation flow

16.4 UX Improvements

FeaturePriorityDescription
Profile completion progressMEDIUMShow % complete
Onboarding tutorialMEDIUMGuide new users
Dark/Light mode toggleLOWTheme switching
Language localizationMEDIUMMulti-language support
Accessibility (a11y)MEDIUMWCAG compliance
Offline supportLOWPWA with service worker
Image compressionMEDIUMClient-side compression before upload

Appendix A: Directory Structure

zaptam-api/
├── prisma/
│   ├── schema.prisma          # Database schema
│   └── seed.ts                # Database seeding
├── src/
│   ├── config/                # Configuration
│   │   ├── database.ts        # Prisma client
│   │   ├── jwt.ts             # JWT config
│   │   ├── multer.ts          # File upload config
│   │   ├── r2.ts              # Cloudflare R2 config
│   │   └── socket.ts          # Socket.IO config
│   ├── controllers/           # Route handlers
│   │   ├── admin/             # Admin controllers
│   │   ├── auth.controller.ts
│   │   ├── match.controller.ts
│   │   ├── message.controller.ts
│   │   ├── profile.controller.ts
│   │   ├── report.controller.ts
│   │   ├── user.controller.ts
│   │   ├── verification.controller.ts
│   │   └── wallet.controller.ts
│   ├── middleware/            # Express middleware
│   │   ├── auth.middleware.ts
│   │   ├── error.middleware.ts
│   │   ├── rateLimit.middleware.ts
│   │   ├── role.middleware.ts
│   │   └── validation.middleware.ts
│   ├── routes/                # Route definitions
│   │   ├── admin/
│   │   ├── auth.routes.ts
│   │   ├── match.routes.ts
│   │   ├── message.routes.ts
│   │   ├── profile.routes.ts
│   │   ├── report.routes.ts
│   │   ├── user.routes.ts
│   │   ├── verification.routes.ts
│   │   ├── wallet.routes.ts
│   │   └── index.ts
│   ├── services/              # Business logic
│   │   ├── auth.service.ts
│   │   ├── match.service.ts
│   │   ├── message.service.ts
│   │   ├── notification.service.ts
│   │   ├── report.service.ts
│   │   ├── trust.service.ts
│   │   ├── user.service.ts
│   │   ├── verification.service.ts
│   │   └── wallet.service.ts
│   ├── sockets/               # WebSocket handlers
│   │   ├── index.ts
│   │   ├── message.socket.ts
│   │   └── presence.socket.ts
│   ├── types/                 # TypeScript types
│   │   └── index.ts
│   ├── utils/                 # Utility functions
│   │   ├── crypto.utils.ts
│   │   ├── helpers.ts
│   │   ├── jwt.utils.ts
│   │   └── r2.utils.ts
│   ├── validators/            # Joi schemas
│   │   ├── auth.validator.ts
│   │   ├── message.validator.ts
│   │   └── profile.validator.ts
│   ├── app.ts                 # Express app setup
│   └── server.ts              # Entry point
└── package.json

zaptam-app/
├── src/
│   ├── api/                   # API client modules
│   │   ├── auth.ts
│   │   ├── client.ts
│   │   ├── matches.ts
│   │   ├── messages.ts
│   │   ├── users.ts
│   │   ├── verification.ts
│   │   └── wallet.ts
│   ├── components/            # React components
│   │   ├── auth/
│   │   ├── layout/
│   │   ├── match/
│   │   ├── message/
│   │   ├── profile/
│   │   ├── ui/
│   │   ├── wallet/
│   │   └── AppLayout.tsx
│   ├── hooks/                 # Custom hooks
│   │   └── useAuth.ts
│   ├── lib/                   # Utilities
│   │   ├── constants.ts
│   │   ├── socket.ts
│   │   └── utils.ts
│   ├── pages/                 # Page components
│   │   ├── auth/
│   │   ├── Conversation.tsx
│   │   ├── Discover.tsx
│   │   ├── Matches.tsx
│   │   ├── Messages.tsx
│   │   ├── Profile.tsx
│   │   ├── Settings.tsx
│   │   └── Wallet.tsx
│   ├── services/              # Service layer
│   │   └── api.ts
│   ├── store/                 # Zustand stores
│   │   ├── auth.ts
│   │   └── socketStore.ts
│   ├── types/                 # TypeScript types
│   │   └── index.ts
│   ├── App.tsx                # Root component
│   └── main.tsx               # Entry point
└── package.json

zaptam-admin/
├── src/
│   ├── components/
│   │   ├── dashboard/
│   │   ├── reports/
│   │   ├── ui/
│   │   ├── users/
│   │   ├── verification/
│   │   └── AdminLayout.tsx
│   ├── hooks/
│   ├── pages/
│   │   ├── Dashboard.tsx
│   │   ├── Login.tsx
│   │   ├── Reports.tsx
│   │   ├── Transactions.tsx
│   │   ├── Users.tsx
│   │   └── Verifications.tsx
│   ├── services/
│   │   └── api.ts
│   ├── store/
│   │   └── auth.ts
│   ├── types/
│   │   └── index.ts
│   ├── App.tsx
│   └── main.tsx
└── package.json

zaptam-landing/
├── src/
│   ├── components/
│   │   ├── layout/
│   │   ├── sections/
│   │   └── ui/
│   ├── hooks/
│   ├── pages/
│   │   ├── About.tsx
│   │   ├── Apply.tsx
│   │   ├── Contact.tsx
│   │   ├── Home.tsx
│   │   ├── HowItWorks.tsx
│   │   ├── Membership.tsx
│   │   ├── Privacy.tsx
│   │   └── Terms.tsx
│   ├── App.tsx
│   └── main.tsx
└── package.json

Appendix B: Environment Variables

zaptam-api

bash
# Database
DATABASE_URL=postgresql://user:pass@host:5432/zaptam

# JWT
JWT_SECRET=your-secret-key
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_EXPIRY=7d

# Cloudflare R2
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET_NAME=zaptam-photos
R2_PUBLIC_URL=https://r2.zaptam.com

# Notification Service
NOTIFICATION_SERVICE_URL=https://notifications.eneza.app
NOTIFICATION_SERVICE_API_KEY=your-api-key
DEFAULT_NOTIFICATION_CHANNEL=whatsapp

# Server
PORT=3000
NODE_ENV=production
CORS_ORIGIN=https://app.zaptam.com

zaptam-app / zaptam-admin

bash
VITE_API_URL=https://api.zaptam.com
VITE_WS_URL=wss://api.zaptam.com

Document generated from codebase analysis. Last updated: March 2026.

One chat. Everything done.