Skip to main content

Core Tables

These are the foundational tables that power the Client Portal platform: clients, users, campaigns, contacts, meetings, calls, and notification preferences.

clients

Client organizations using the platform. Each client represents a legal search firm.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
nametextNOOrganization name
emailtextYESPrimary contact email
phonetextYESPrimary contact phone
websitetextYESCompany website URL
statustextYES'active'Account status (active, inactive, onboarding)
availability_settingsjsonbYESWeekly availability for booking (used by client-mode scheduling)
timezonetextYES'America/New_York'Client's timezone
created_attimestamptzYESnow()Record creation timestamp
updated_attimestamptzYESnow()Last update timestamp

The availability_settings JSONB structure:

{
"monday": { "enabled": true, "start": "09:00", "end": "17:00" },
"tuesday": { "enabled": true, "start": "09:00", "end": "17:00" },
"wednesday": { "enabled": true, "start": "09:00", "end": "17:00" },
"thursday": { "enabled": true, "start": "09:00", "end": "17:00" },
"friday": { "enabled": true, "start": "09:00", "end": "17:00" },
"saturday": { "enabled": false, "start": "09:00", "end": "17:00" },
"sunday": { "enabled": false, "start": "09:00", "end": "17:00" }
}

user_profiles

Extended metadata for each user. Linked to auth.users via user_id.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
user_iduuidNOFK to auth.users.id (unique)
display_nametextYESUser's display name
avatar_urltextYESProfile image URL
client_iduuidYESFK to clients.id (null for internal users)
timezonetextYES'America/New_York'User's timezone
availability_settingsjsonbYESWeekly availability (same format as clients, used by internal booking)
created_attimestamptzYESnow()
updated_attimestamptzYESnow()
Internal vs Client Users
  • Internal users (admin, bdr): client_id is NULL, availability_settings is used for internal booking links.
  • Client users: client_id points to their organization. Their availability comes from the clients table instead.

user_roles

Role assignments linking users to roles. A user can have multiple roles.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
user_iduuidNOFK to auth.users.id
roletextNORole name: admin, bdr, or client
created_attimestamptzYESnow()

Unique constraint: (user_id, role) -- a user cannot have the same role twice.


campaigns

Marketing/outreach campaigns owned by a client. Each campaign targets a specific market of attorneys.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
client_iduuidNOFK to clients.id
nametextNOCampaign name
statustextYES'active'active, paused, completed, draft
market_iduuidYESFK to markets.id (optional market linkage)
descriptiontextYESCampaign description
start_datedateYESCampaign start date
end_datedateYESCampaign end date
created_attimestamptzYESnow()
updated_attimestamptzYESnow()

contacts

People within campaigns. Typically attorneys being contacted as part of outreach.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
campaign_iduuidYESFK to campaigns.id
client_iduuidYESFK to clients.id
nametextYESFull name
first_nametextYESFirst name
last_nametextYESLast name
emailtextYESEmail address
phonetextYESPhone number
firmtextYESLaw firm name
titletextYESJob title
senioritytextYESSeniority level
linkedin_urltextYESLinkedIn profile URL
citytextYESCity
statetextYESState
statustextYES'active'Contact status
notestextYESFree-text notes
created_attimestamptzYESnow()
updated_attimestamptzYESnow()

meetings

Scheduled meetings with contacts. Created when someone books via a client booking link.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
contact_iduuidYESFK to contacts.id
client_iduuidYESFK to clients.id
booking_link_iduuidYESFK to booking_links.id
titletextYESMeeting title
scheduled_fortimestamptzNOMeeting date/time
duration_minutesintegerYES30Duration in minutes
statustextYES'scheduled'scheduled, completed, cancelled, no_show
booker_nametextYESName of person who booked
booker_emailtextYESEmail of person who booked
booker_phonetextYESPhone of person who booked
booking_sourcetextYESmanual or booking_link
calendar_event_idtextYESID from Google/Outlook calendar
meeting_linktextYESVideo call URL (Google Meet / Teams)
confirmation_sent_attimestamptzYESWhen confirmation email was sent
reminder_24h_sent_attimestamptzYESWhen 24h reminder was sent
reminder_1h_sent_attimestamptzYESWhen 1h reminder was sent
outcome_notestextYESPost-meeting notes
created_attimestamptzYESnow()
updated_attimestamptzYESnow()

calls

Call records for client campaigns. Contains disposition, transcript, recording URL, and AI-generated summary.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
contact_iduuidYESFK to contacts.id
campaign_iduuidYESFK to campaigns.id
client_iduuidYESFK to clients.id
dispositiontextYESCall outcome (see 9 canonical dispositions below)
transcripttextYESFull call transcript (alias: transcript_raw)
recording_urltextYESURL to call recording in Supabase Storage
durationintegerYESCall duration in seconds
ai_summaryjsonbYESAI-generated summary (key_points, sentiment, etc.)
notestextYESBDR notes
called_attimestamptzYESWhen the call happened
called_byuuidYESFK to auth.users.id (BDR who made the call)
external_call_idtextYESGHL call ID (used for deduplication)
phone_numbertextYESPhone number dialed
created_attimestamptzYESnow()
updated_attimestamptzYESnow()

9 Canonical Dispositions (Title Case)

DispositionCategoryDescription
No AnswerAccessPhone rang, nobody picked up
VoicemailAccessReached voicemail
GatekeeperAccessReached assistant/receptionist, blocked
Incorrect NumberAccessWrong number or disconnected
Not InterestedConversationConnected but declined to engage
Callback RequestedConversationAsked to call back later
Future PotentialOpportunityInterested but not now
Meeting BookedOpportunityMeeting scheduled
Do Not ContactHard stopRequested no further contact
Disposition is TEXT

The disposition column is TEXT, not an enum. It was migrated from a call_disposition enum via migration 20260210200001_convert_disposition_to_text.sql. Always use the exact Title Case values above.


notification_preferences

Per-user notification settings controlling which emails and in-app notifications are enabled.

ColumnTypeNullableDefaultDescription
iduuidNOgen_random_uuid()Primary key
user_iduuidNOFK to auth.users.id (unique)
email_meeting_bookedbooleanYEStrueEmail when a meeting is booked
email_meeting_reminderbooleanYEStrueEmail meeting reminders
email_meeting_cancelledbooleanYEStrueEmail when meeting cancelled
email_weekly_summarybooleanYEStrueWeekly summary email
in_app_new_signalbooleanYEStrueIn-app notification for new signals
in_app_call_loggedbooleanYEStrueIn-app notification for new calls
created_attimestamptzYESnow()
updated_attimestamptzYESnow()

Entity Relationship Diagram