Overview
upLegal uses PostgreSQL via Supabase with Row Level Security (RLS) for access control. The database is organized into core tables for users, appointments, payments, messaging, and reviews.Core Tables
profiles
Stores user account information for both clients and lawyers.Primary key, references Supabase Auth user
User’s email address
User role:
'client' or 'lawyer'User’s first name
User’s last name
Chilean RUT (tax ID) for lawyers
Whether lawyer is verified through PJUD
Profile picture URL from Supabase Storage
Lawyer bio/description
Array of legal specialties (e.g.,
["Derecho Civil", "Derecho Penal"])Lawyer’s hourly rate in Chilean pesos
One-time fee to initiate conversation
Lawyer’s city/region
Weekly availability grid (JSON object)
MercadoPago account ID for payouts
Current balance from completed appointments
Profile completion percentage (0-100)
Account creation timestamp
Last profile update timestamp
appointments
Scheduled consultations between clients and lawyers.Primary key
Client user ID
Lawyer user ID
Scheduled date (YYYY-MM-DD)
Scheduled time (HH:MM)
Duration in minutes (30, 60, 90, or 120)
Type:
'video', 'phone', or 'in-person'Preferred contact:
'google_meet', 'phone', 'address'Status:
'pending', 'confirmed', 'completed', 'cancelled'Total price in CLP
Lawyer’s payout amount (80% of price)
Currency code
Google Meet link for video consultations
Client name
Client email
Client phone number
Meeting address for in-person consultations
Consultation description/notes
Lawyer’s private notes
bookings
Payment-linked booking records created via MercadoPago.Primary key
Client user ID (nullable for guest bookings)
Lawyer user ID, foreign key to
profiles.user_idClient name
Client email
Appointment date
Appointment time
Duration in minutes
Total price paid
Booking status:
'pending', 'confirmed', 'cancelled'MercadoPago payment status:
'approved', 'pending', 'rejected'MercadoPago payment ID
MercadoPago payment preference ID
Timestamp when booking was confirmed
Timestamp when booking was cancelled
messages
Real-time chat messages between clients and lawyers.Primary key
Foreign key to
conversations.idUser ID of message sender
Message text content
Message status:
'sending', 'sent', 'delivered', 'read'URL to file attachment (if any)
Message timestamp
Timestamp when message was read
conversations
Message threads between clients and lawyers.Primary key
Client user ID
Lawyer user ID
Whether client has paid contact fee to initiate conversation
Timestamp of most recent message
Conversation creation timestamp
reviews
Client reviews and ratings for lawyers.Primary key
Lawyer being reviewed
Client who wrote the review
Related appointment (if applicable)
Star rating (1-5)
Written review (max 1,000 characters)
Review status:
'pending', 'approved', 'rejected'Number of “helpful” votes
Review creation timestamp
payments
Payment transaction records.Primary key
Client user ID
Lawyer user ID
Payment amount in CLP
Platform fee (10% of amount)
Lawyer payout amount (90% of amount)
Type:
'appointment', 'contact_fee', 'consultation'Status:
'pending', 'approved', 'rejected', 'refunded'MercadoPago payment ID
Payment timestamp
notifications
In-app notification queue.Primary key
Recipient user ID
Notification type:
'appointment', 'message', 'payment', 'system'Notification title
Notification content
Whether notification has been read
URL to navigate to when clicked
Notification timestamp
Table Relationships
Row Level Security (RLS)
All tables have RLS policies enabled:profiles
profiles
- Users can read all public lawyer profiles
- Users can update only their own profile
- Service role can perform all operations
appointments
appointments
- Clients can read/update their own appointments
- Lawyers can read/update appointments where they are the lawyer
- Service role can perform all operations
messages
messages
- Users can only read messages in conversations they participate in
- Users can only create messages in their own conversations
- Service role can perform all operations
reviews
reviews
- All users can read approved reviews
- Clients can create reviews for completed appointments
- Lawyers cannot edit or delete reviews
- Service role can moderate reviews
payments
payments
- Clients can read their own payment history
- Lawyers can read payments where they are the lawyer
- No client/lawyer write access (server-side only)
- Service role can perform all operations
Indexes
Key indexes for query performance:profiles.email- Unique indexprofiles.role- Filter by user typeprofiles.pjud_verified- Filter verified lawyersappointments.lawyer_id- Lawyer’s appointmentsappointments.user_id- Client’s appointmentsappointments.appointment_date- Date-based queriesmessages.conversation_id- Conversation messagesmessages.created_at- Message orderingreviews.lawyer_id- Lawyer reviewsbookings.payment_id- Payment reconciliation
Database Functions
Custom PostgreSQL functions:get_lawyer_earnings(lawyer_id UUID)
Calculates total earnings for a lawyer from completed appointments.
Migrations
Database schema is versioned using Supabase migrations in/supabase/migrations/:
- Initial schema setup
- Profile table with RLS policies
- Payment tables and earnings functions
- Storage buckets for avatars
- Appointment and booking tables
Next Steps
API Reference
Explore API endpoints for database operations
Supabase Integration
Learn how to query the database with Supabase client
Architecture
Understand the overall system architecture
Local Setup
Set up the database for local development