Skip to content

YeboSafe Database Models

YeboSafe uses Prisma ORM with PostgreSQL.

Merchant

Registered businesses using YeboSafe.

prisma
model Merchant {
  id         String   @id @default(cuid())
  name       String
  email      String   @unique
  password   String                // bcrypt hashed
  webhookUrl String?               // Default webhook endpoint
  isActive   Boolean  @default(true)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  
  // Relations
  apiKeys    ApiKey[]
  escrows    EscrowTransaction[] @relation("MerchantEscrows")
  wallet     MerchantWallet?
}

ApiKey

API keys for merchant authentication.

prisma
model ApiKey {
  id         String    @id @default(cuid())
  key        String    @unique       // Full key (hashed in prod)
  prefix     String                   // First 8 chars for identification
  name       String?                  // Optional friendly name
  isActive   Boolean   @default(true)
  merchantId String
  merchant   Merchant  @relation(fields: [merchantId], references: [id])
  createdAt  DateTime  @default(now())
  lastUsedAt DateTime?
}

EscrowTransaction

Core escrow record.

prisma
model EscrowTransaction {
  id             String        @id @default(cuid())
  reference      String        @unique @default(cuid())  // Public reference
  
  // Merchant
  merchantId     String
  merchant       Merchant      @relation("MerchantEscrows", fields: [merchantId], references: [id])
  
  // Payer info
  payerName      String?
  payerEmail     String?
  payerPhone     String?
  
  // Transaction details
  amount         Decimal       @db.Decimal(12, 2)
  currency       String        @default("USD")
  description    String?
  metadata       Json?                                    // Custom merchant data
  
  // Status
  status         EscrowStatus  @default(PENDING)
  completionCode String        @unique                    // 6-digit code for release
  webhookUrl     String?                                  // Override merchant default
  
  // Timestamps
  completedAt    DateTime?
  disputedAt     DateTime?
  disputeReason  String?
  cancelledAt    DateTime?
  cancelReason   String?
  refundedAt     DateTime?
  createdAt      DateTime      @default(now())
  updatedAt      DateTime      @updatedAt
  
  // Relations
  logs           EscrowLog[]
}

enum EscrowStatus {
  PENDING     // Created, awaiting merchant acceptance
  ACCEPTED    // Merchant committed to deliver
  COMPLETED   // Completion code used, funds released
  REFUSED     // Merchant declined
  DISPUTED    // Dispute opened
  CANCELLED   // Cancelled before completion
  REFUNDED    // Funds returned to payer
}

EscrowLog

Audit trail for escrow actions.

prisma
model EscrowLog {
  id        String            @id @default(cuid())
  escrowId  String
  escrow    EscrowTransaction @relation(fields: [escrowId], references: [id])
  
  action    String            // 'created', 'accepted', 'completed', etc.
  actorId   String?           // Who performed the action
  metadata  Json?             // Additional context
  createdAt DateTime          @default(now())
}

MerchantWallet

Merchant balance tracking.

prisma
model MerchantWallet {
  id           String        @id @default(cuid())
  merchantId   String        @unique
  merchant     Merchant      @relation(fields: [merchantId], references: [id])
  
  balance      Decimal       @default(0) @db.Decimal(12, 2)
  currency     String        @default("USD")
  
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt
  
  transactions WalletEntry[]
}

WalletEntry

Wallet transaction history.

prisma
model WalletEntry {
  id          String         @id @default(cuid())
  walletId    String
  wallet      MerchantWallet @relation(fields: [walletId], references: [id])
  
  type        EntryType
  amount      Decimal        @db.Decimal(12, 2)
  description String?
  reference   String?        // Link to escrow ID
  createdAt   DateTime       @default(now())
}

enum EntryType {
  CREDIT    // Funds added (escrow completion)
  DEBIT     // Funds withdrawn
}

WebhookEvent

Webhook delivery tracking.

prisma
model WebhookEvent {
  id         String   @id @default(cuid())
  merchantId String
  event      String                    // 'escrow.created', etc.
  payload    Json
  delivered  Boolean  @default(false)
  attempts   Int      @default(0)
  lastError  String?
  createdAt  DateTime @default(now())
}

Relationships Diagram

Merchant 1───────* ApiKey

    ├──────────1 MerchantWallet 1──* WalletEntry

    └──────────* EscrowTransaction 1──* EscrowLog

                        └───────────── WebhookEvent (tracked separately)

Example Flow

sql
-- 1. Create escrow
INSERT INTO EscrowTransaction (merchantId, amount, status, completionCode)
VALUES ('merch_123', 100.00, 'PENDING', '123456');

-- 2. Accept
UPDATE EscrowTransaction SET status = 'ACCEPTED' WHERE id = 'esc_123';

-- 3. Complete (with code verification)
UPDATE EscrowTransaction SET status = 'COMPLETED', completedAt = NOW()
WHERE completionCode = '123456' AND status = 'ACCEPTED';

-- 4. Credit wallet
UPDATE MerchantWallet SET balance = balance + 100.00
WHERE merchantId = 'merch_123';

-- 5. Log transaction
INSERT INTO WalletEntry (walletId, type, amount, reference)
VALUES ('wallet_123', 'CREDIT', 100.00, 'esc_123');

One chat. Everything done.